1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
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.
8 
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.
12 
13 See the GNU General Public License for more details.
14 
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.
18 
19 */
20 // r_main.c
21 
22 #include "quakedef.h"
23 #include "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
31 
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36 
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47 
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50 
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52 
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59 
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64 
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"};
77 
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 (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
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) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
83 
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_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
97 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)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 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"};
101 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"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 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"};
104 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"};
105 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"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 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)"};
115 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)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
122 
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
126 
127 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
131 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
132 
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 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."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 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."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
144 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."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 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"};
147 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"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 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"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 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
158 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
159 
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
168 
169 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)"};
170 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"};
171 
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
175 
176 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"};
177 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"};
178 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"};
179 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
180 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
181 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"};
182 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)"};
183 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)"};
184 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
185 
186 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
187 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)"};
188 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
189 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)"};
190 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
191 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)"};
192 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)"};
193 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
194 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"};
195 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."};
196 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
197 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)"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 
206 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)"};
207 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)"};
208 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
209 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"};
210 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
211 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
212 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
213 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"};
214 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"};
215 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)"};
216 
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
221 
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
224 
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
231 
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
242 
243 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"};
244 
245 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"};
246 
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
248 
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
250 
251 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)"};
252 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)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
255 
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 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"};
258 
259 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."};
260 
261 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)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
263 {
264 	{CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265 	{CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266 	{CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267 	{CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
268 };
269 
270 extern cvar_t v_glslgamma_2d;
271 
272 extern qboolean v_flipped_state;
273 
274 r_framebufferstate_t r_fb;
275 
276 /// shadow volume bsp struct with automatically growing nodes buffer
277 svbsp_t r_svbsp;
278 
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
280 
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
294 
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
297 {
298 	char basename[64];
299 	rtexture_t *texture;
300 }
301 cubemapinfo_t;
302 
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
305 
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
309 
310 typedef struct r_qwskincache_s
311 {
312 	char name[MAX_QPATH];
313 	skinframe_t *skinframe;
314 }
315 r_qwskincache_t;
316 
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
319 
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 extern const float r_d3dscreenvertex3f[12];
323 const float r_screenvertex3f[12] =
324 {
325 	0, 0, 0,
326 	1, 0, 0,
327 	1, 1, 0,
328 	0, 1, 0
329 };
330 const float r_d3dscreenvertex3f[12] =
331 {
332 	0, 1, 0,
333 	1, 1, 0,
334 	1, 0, 0,
335 	0, 0, 0
336 };
337 
R_ModulateColors(float * in,float * out,int verts,float r,float g,float b)338 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
339 {
340 	int i;
341 	for (i = 0;i < verts;i++)
342 	{
343 		out[0] = in[0] * r;
344 		out[1] = in[1] * g;
345 		out[2] = in[2] * b;
346 		out[3] = in[3];
347 		in += 4;
348 		out += 4;
349 	}
350 }
351 
R_FillColors(float * out,int verts,float r,float g,float b,float a)352 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
353 {
354 	int i;
355 	for (i = 0;i < verts;i++)
356 	{
357 		out[0] = r;
358 		out[1] = g;
359 		out[2] = b;
360 		out[3] = a;
361 		out += 4;
362 	}
363 }
364 
365 // FIXME: move this to client?
FOG_clear(void)366 void FOG_clear(void)
367 {
368 	if (gamemode == GAME_NEHAHRA)
369 	{
370 		Cvar_Set("gl_fogenable", "0");
371 		Cvar_Set("gl_fogdensity", "0.2");
372 		Cvar_Set("gl_fogred", "0.3");
373 		Cvar_Set("gl_foggreen", "0.3");
374 		Cvar_Set("gl_fogblue", "0.3");
375 	}
376 	r_refdef.fog_density = 0;
377 	r_refdef.fog_red = 0;
378 	r_refdef.fog_green = 0;
379 	r_refdef.fog_blue = 0;
380 	r_refdef.fog_alpha = 1;
381 	r_refdef.fog_start = 0;
382 	r_refdef.fog_end = 16384;
383 	r_refdef.fog_height = 1<<30;
384 	r_refdef.fog_fadedepth = 128;
385 	memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
386 }
387 
R_BuildBlankTextures(void)388 static void R_BuildBlankTextures(void)
389 {
390 	unsigned char data[4];
391 	data[2] = 128; // normal X
392 	data[1] = 128; // normal Y
393 	data[0] = 255; // normal Z
394 	data[3] = 255; // height
395 	r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 	data[0] = 255;
397 	data[1] = 255;
398 	data[2] = 255;
399 	data[3] = 255;
400 	r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 	data[0] = 128;
402 	data[1] = 128;
403 	data[2] = 128;
404 	data[3] = 255;
405 	r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406 	data[0] = 0;
407 	data[1] = 0;
408 	data[2] = 0;
409 	data[3] = 255;
410 	r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
411 }
412 
R_BuildNoTexture(void)413 static void R_BuildNoTexture(void)
414 {
415 	int x, y;
416 	unsigned char pix[16][16][4];
417 	// this makes a light grey/dark grey checkerboard texture
418 	for (y = 0;y < 16;y++)
419 	{
420 		for (x = 0;x < 16;x++)
421 		{
422 			if ((y < 8) ^ (x < 8))
423 			{
424 				pix[y][x][0] = 128;
425 				pix[y][x][1] = 128;
426 				pix[y][x][2] = 128;
427 				pix[y][x][3] = 255;
428 			}
429 			else
430 			{
431 				pix[y][x][0] = 64;
432 				pix[y][x][1] = 64;
433 				pix[y][x][2] = 64;
434 				pix[y][x][3] = 255;
435 			}
436 		}
437 	}
438 	r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
439 }
440 
R_BuildWhiteCube(void)441 static void R_BuildWhiteCube(void)
442 {
443 	unsigned char data[6*1*1*4];
444 	memset(data, 255, sizeof(data));
445 	r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446 }
447 
R_BuildNormalizationCube(void)448 static void R_BuildNormalizationCube(void)
449 {
450 	int x, y, side;
451 	vec3_t v;
452 	vec_t s, t, intensity;
453 #define NORMSIZE 64
454 	unsigned char *data;
455 	data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
456 	for (side = 0;side < 6;side++)
457 	{
458 		for (y = 0;y < NORMSIZE;y++)
459 		{
460 			for (x = 0;x < NORMSIZE;x++)
461 			{
462 				s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
463 				t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464 				switch(side)
465 				{
466 				default:
467 				case 0:
468 					v[0] = 1;
469 					v[1] = -t;
470 					v[2] = -s;
471 					break;
472 				case 1:
473 					v[0] = -1;
474 					v[1] = -t;
475 					v[2] = s;
476 					break;
477 				case 2:
478 					v[0] = s;
479 					v[1] = 1;
480 					v[2] = t;
481 					break;
482 				case 3:
483 					v[0] = s;
484 					v[1] = -1;
485 					v[2] = -t;
486 					break;
487 				case 4:
488 					v[0] = s;
489 					v[1] = -t;
490 					v[2] = 1;
491 					break;
492 				case 5:
493 					v[0] = -s;
494 					v[1] = -t;
495 					v[2] = -1;
496 					break;
497 				}
498 				intensity = 127.0f / sqrt(DotProduct(v, v));
499 				data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
500 				data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
501 				data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
502 				data[((side*64+y)*64+x)*4+3] = 255;
503 			}
504 		}
505 	}
506 	r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
507 	Mem_Free(data);
508 }
509 
R_BuildFogTexture(void)510 static void R_BuildFogTexture(void)
511 {
512 	int x, b;
513 #define FOGWIDTH 256
514 	unsigned char data1[FOGWIDTH][4];
515 	//unsigned char data2[FOGWIDTH][4];
516 	double d, r, alpha;
517 
518 	r_refdef.fogmasktable_start = r_refdef.fog_start;
519 	r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
520 	r_refdef.fogmasktable_range = r_refdef.fogrange;
521 	r_refdef.fogmasktable_density = r_refdef.fog_density;
522 
523 	r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
524 	for (x = 0;x < FOGMASKTABLEWIDTH;x++)
525 	{
526 		d = (x * r - r_refdef.fogmasktable_start);
527 		if(developer_extra.integer)
528 			Con_DPrintf("%f ", d);
529 		d = max(0, d);
530 		if (r_fog_exp2.integer)
531 			alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
532 		else
533 			alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
534 		if(developer_extra.integer)
535 			Con_DPrintf(" : %f ", alpha);
536 		alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
537 		if(developer_extra.integer)
538 			Con_DPrintf(" = %f\n", alpha);
539 		r_refdef.fogmasktable[x] = bound(0, alpha, 1);
540 	}
541 
542 	for (x = 0;x < FOGWIDTH;x++)
543 	{
544 		b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
545 		data1[x][0] = b;
546 		data1[x][1] = b;
547 		data1[x][2] = b;
548 		data1[x][3] = 255;
549 		//data2[x][0] = 255 - b;
550 		//data2[x][1] = 255 - b;
551 		//data2[x][2] = 255 - b;
552 		//data2[x][3] = 255;
553 	}
554 	if (r_texture_fogattenuation)
555 	{
556 		R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557 		//R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558 	}
559 	else
560 	{
561 		r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
562 		//r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
563 	}
564 }
565 
R_BuildFogHeightTexture(void)566 static void R_BuildFogHeightTexture(void)
567 {
568 	unsigned char *inpixels;
569 	int size;
570 	int x;
571 	int y;
572 	int j;
573 	float c[4];
574 	float f;
575 	inpixels = NULL;
576 	strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
577 	if (r_refdef.fogheighttexturename[0])
578 		inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
579 	if (!inpixels)
580 	{
581 		r_refdef.fog_height_tablesize = 0;
582 		if (r_texture_fogheighttexture)
583 			R_FreeTexture(r_texture_fogheighttexture);
584 		r_texture_fogheighttexture = NULL;
585 		if (r_refdef.fog_height_table2d)
586 			Mem_Free(r_refdef.fog_height_table2d);
587 		r_refdef.fog_height_table2d = NULL;
588 		if (r_refdef.fog_height_table1d)
589 			Mem_Free(r_refdef.fog_height_table1d);
590 		r_refdef.fog_height_table1d = NULL;
591 		return;
592 	}
593 	size = image_width;
594 	r_refdef.fog_height_tablesize = size;
595 	r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
596 	r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
597 	memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
598 	Mem_Free(inpixels);
599 	// LordHavoc: now the magic - what is that table2d for?  it is a cooked
600 	// average fog color table accounting for every fog layer between a point
601 	// and the camera.  (Note: attenuation is handled separately!)
602 	for (y = 0;y < size;y++)
603 	{
604 		for (x = 0;x < size;x++)
605 		{
606 			Vector4Clear(c);
607 			f = 0;
608 			if (x < y)
609 			{
610 				for (j = x;j <= y;j++)
611 				{
612 					Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613 					f++;
614 				}
615 			}
616 			else
617 			{
618 				for (j = x;j >= y;j--)
619 				{
620 					Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
621 					f++;
622 				}
623 			}
624 			f = 1.0f / f;
625 			r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
626 			r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
627 			r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
628 			r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
629 		}
630 	}
631 	r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
632 }
633 
634 //=======================================================================================================================================================
635 
636 static const char *builtinshaderstrings[] =
637 {
638 #include "shader_glsl.h"
639 0
640 };
641 
642 const char *builtinhlslshaderstrings[] =
643 {
644 #include "shader_hlsl.h"
645 0
646 };
647 
648 //=======================================================================================================================================================
649 
650 typedef struct shaderpermutationinfo_s
651 {
652 	const char *pretext;
653 	const char *name;
654 }
655 shaderpermutationinfo_t;
656 
657 typedef struct shadermodeinfo_s
658 {
659 	const char *sourcebasename;
660 	const char *extension;
661 	const char **builtinshaderstrings;
662 	const char *pretext;
663 	const char *name;
664 	char *filename;
665 	char *builtinstring;
666 	int builtincrc;
667 }
668 shadermodeinfo_t;
669 
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
672 {
673 	{"#define USEDIFFUSE\n", " diffuse"},
674 	{"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
675 	{"#define USEVIEWTINT\n", " viewtint"},
676 	{"#define USECOLORMAPPING\n", " colormapping"},
677 	{"#define USESATURATION\n", " saturation"},
678 	{"#define USEFOGINSIDE\n", " foginside"},
679 	{"#define USEFOGOUTSIDE\n", " fogoutside"},
680 	{"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
681 	{"#define USEFOGALPHAHACK\n", " fogalphahack"},
682 	{"#define USEGAMMARAMPS\n", " gammaramps"},
683 	{"#define USECUBEFILTER\n", " cubefilter"},
684 	{"#define USEGLOW\n", " glow"},
685 	{"#define USEBLOOM\n", " bloom"},
686 	{"#define USESPECULAR\n", " specular"},
687 	{"#define USEPOSTPROCESSING\n", " postprocessing"},
688 	{"#define USEREFLECTION\n", " reflection"},
689 	{"#define USEOFFSETMAPPING\n", " offsetmapping"},
690 	{"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
691 	{"#define USESHADOWMAP2D\n", " shadowmap2d"},
692 	{"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
693 	{"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
694 	{"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
695 	{"#define USEALPHAKILL\n", " alphakill"},
696 	{"#define USEREFLECTCUBE\n", " reflectcube"},
697 	{"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
698 	{"#define USEBOUNCEGRID\n", " bouncegrid"},
699 	{"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
700 	{"#define USETRIPPY\n", " trippy"},
701 	{"#define USEDEPTHRGB\n", " depthrgb"},
702 	{"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
703 	{"#define USESKELETAL\n", " skeletal"},
704 	{"#define USEOCCLUDE\n", " occlude"}
705 };
706 
707 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
708 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
709 {
710 	// SHADERLANGUAGE_GLSL
711 	{
712 		{"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
713 		{"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
714 		{"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715 		{"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
716 		{"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
718 		{"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
719 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724 		{"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
725 		{"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
726 		{"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
727 		{"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728 		{"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 	},
730 	// SHADERLANGUAGE_HLSL
731 	{
732 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
733 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
734 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
735 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
736 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
737 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
738 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
739 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
740 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
741 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
742 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
743 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
744 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
745 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
746 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
747 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
748 		{"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
749 	},
750 };
751 
752 struct r_glsl_permutation_s;
753 typedef struct r_glsl_permutation_s
754 {
755 	/// hash lookup data
756 	struct r_glsl_permutation_s *hashnext;
757 	unsigned int mode;
758 	dpuint64 permutation;
759 
760 	/// indicates if we have tried compiling this permutation already
761 	qboolean compiled;
762 	/// 0 if compilation failed
763 	int program;
764 	// texture units assigned to each detected uniform
765 	int tex_Texture_First;
766 	int tex_Texture_Second;
767 	int tex_Texture_GammaRamps;
768 	int tex_Texture_Normal;
769 	int tex_Texture_Color;
770 	int tex_Texture_Gloss;
771 	int tex_Texture_Glow;
772 	int tex_Texture_SecondaryNormal;
773 	int tex_Texture_SecondaryColor;
774 	int tex_Texture_SecondaryGloss;
775 	int tex_Texture_SecondaryGlow;
776 	int tex_Texture_Pants;
777 	int tex_Texture_Shirt;
778 	int tex_Texture_FogHeightTexture;
779 	int tex_Texture_FogMask;
780 	int tex_Texture_Lightmap;
781 	int tex_Texture_Deluxemap;
782 	int tex_Texture_Attenuation;
783 	int tex_Texture_Cube;
784 	int tex_Texture_Refraction;
785 	int tex_Texture_Reflection;
786 	int tex_Texture_ShadowMap2D;
787 	int tex_Texture_CubeProjection;
788 	int tex_Texture_ScreenNormalMap;
789 	int tex_Texture_ScreenDiffuse;
790 	int tex_Texture_ScreenSpecular;
791 	int tex_Texture_ReflectMask;
792 	int tex_Texture_ReflectCube;
793 	int tex_Texture_BounceGrid;
794 	/// locations of detected uniforms in program object, or -1 if not found
795 	int loc_Texture_First;
796 	int loc_Texture_Second;
797 	int loc_Texture_GammaRamps;
798 	int loc_Texture_Normal;
799 	int loc_Texture_Color;
800 	int loc_Texture_Gloss;
801 	int loc_Texture_Glow;
802 	int loc_Texture_SecondaryNormal;
803 	int loc_Texture_SecondaryColor;
804 	int loc_Texture_SecondaryGloss;
805 	int loc_Texture_SecondaryGlow;
806 	int loc_Texture_Pants;
807 	int loc_Texture_Shirt;
808 	int loc_Texture_FogHeightTexture;
809 	int loc_Texture_FogMask;
810 	int loc_Texture_Lightmap;
811 	int loc_Texture_Deluxemap;
812 	int loc_Texture_Attenuation;
813 	int loc_Texture_Cube;
814 	int loc_Texture_Refraction;
815 	int loc_Texture_Reflection;
816 	int loc_Texture_ShadowMap2D;
817 	int loc_Texture_CubeProjection;
818 	int loc_Texture_ScreenNormalMap;
819 	int loc_Texture_ScreenDiffuse;
820 	int loc_Texture_ScreenSpecular;
821 	int loc_Texture_ReflectMask;
822 	int loc_Texture_ReflectCube;
823 	int loc_Texture_BounceGrid;
824 	int loc_Alpha;
825 	int loc_BloomBlur_Parameters;
826 	int loc_ClientTime;
827 	int loc_Color_Ambient;
828 	int loc_Color_Diffuse;
829 	int loc_Color_Specular;
830 	int loc_Color_Glow;
831 	int loc_Color_Pants;
832 	int loc_Color_Shirt;
833 	int loc_DeferredColor_Ambient;
834 	int loc_DeferredColor_Diffuse;
835 	int loc_DeferredColor_Specular;
836 	int loc_DeferredMod_Diffuse;
837 	int loc_DeferredMod_Specular;
838 	int loc_DistortScaleRefractReflect;
839 	int loc_EyePosition;
840 	int loc_FogColor;
841 	int loc_FogHeightFade;
842 	int loc_FogPlane;
843 	int loc_FogPlaneViewDist;
844 	int loc_FogRangeRecip;
845 	int loc_LightColor;
846 	int loc_LightDir;
847 	int loc_LightPosition;
848 	int loc_OffsetMapping_ScaleSteps;
849 	int loc_OffsetMapping_LodDistance;
850 	int loc_OffsetMapping_Bias;
851 	int loc_PixelSize;
852 	int loc_ReflectColor;
853 	int loc_ReflectFactor;
854 	int loc_ReflectOffset;
855 	int loc_RefractColor;
856 	int loc_Saturation;
857 	int loc_ScreenCenterRefractReflect;
858 	int loc_ScreenScaleRefractReflect;
859 	int loc_ScreenToDepth;
860 	int loc_ShadowMap_Parameters;
861 	int loc_ShadowMap_TextureScale;
862 	int loc_SpecularPower;
863 	int loc_Skeletal_Transform12;
864 	int loc_UserVec1;
865 	int loc_UserVec2;
866 	int loc_UserVec3;
867 	int loc_UserVec4;
868 	int loc_ViewTintColor;
869 	int loc_ViewToLight;
870 	int loc_ModelToLight;
871 	int loc_TexMatrix;
872 	int loc_BackgroundTexMatrix;
873 	int loc_ModelViewProjectionMatrix;
874 	int loc_ModelViewMatrix;
875 	int loc_PixelToScreenTexCoord;
876 	int loc_ModelToReflectCube;
877 	int loc_ShadowMapMatrix;
878 	int loc_BloomColorSubtract;
879 	int loc_NormalmapScrollBlend;
880 	int loc_BounceGridMatrix;
881 	int loc_BounceGridIntensity;
882 	/// uniform block bindings
883 	int ubibind_Skeletal_Transform12_UniformBlock;
884 	/// uniform block indices
885 	int ubiloc_Skeletal_Transform12_UniformBlock;
886 }
887 r_glsl_permutation_t;
888 
889 #define SHADERPERMUTATION_HASHSIZE 256
890 
891 
892 // non-degradable "lightweight" shader parameters to keep the permutations simpler
893 // these can NOT degrade! only use for simple stuff
894 enum
895 {
896 	SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
897 	SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
898 	SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
899 	SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
900 	SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
901 	SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
902 	SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
903 	SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
904 	SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
905 	SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
906 	SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
907 	SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
908 	SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
909 	SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
910 };
911 #define SHADERSTATICPARMS_COUNT 14
912 
913 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
914 static int shaderstaticparms_count = 0;
915 
916 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
917 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
918 
919 extern qboolean r_shadow_shadowmapsampler;
920 extern int r_shadow_shadowmappcf;
R_CompileShader_CheckStaticParms(void)921 qboolean R_CompileShader_CheckStaticParms(void)
922 {
923 	static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
924 	memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
925 	memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
926 
927 	// detect all
928 	if (r_glsl_saturation_redcompensate.integer)
929 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
930 	if (r_glsl_vertextextureblend_usebothalphas.integer)
931 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
932 	if (r_shadow_glossexact.integer)
933 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
934 	if (r_glsl_postprocess.integer)
935 	{
936 		if (r_glsl_postprocess_uservec1_enable.integer)
937 			R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
938 		if (r_glsl_postprocess_uservec2_enable.integer)
939 			R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
940 		if (r_glsl_postprocess_uservec3_enable.integer)
941 			R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
942 		if (r_glsl_postprocess_uservec4_enable.integer)
943 			R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
944 	}
945 	if (r_fxaa.integer)
946 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
947 	if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
948 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
949 
950 	if (r_shadow_shadowmapsampler)
951 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
952 	if (r_shadow_shadowmappcf > 1)
953 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
954 	else if (r_shadow_shadowmappcf)
955 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
956 	if (r_celshading.integer)
957 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
958 	if (r_celoutlines.integer)
959 		R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
960 
961 	return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
962 }
963 
964 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
965 	if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
966 		shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
967 	else \
968 		shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
R_CompileShader_AddStaticParms(unsigned int mode,dpuint64 permutation)969 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
970 {
971 	shaderstaticparms_count = 0;
972 
973 	// emit all
974 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
975 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
976 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
977 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
978 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
979 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
980 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
981 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
982 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
983 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
984 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
985 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
986 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
987 	R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
988 }
989 
990 /// information about each possible shader permutation
991 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
992 /// currently selected permutation
993 r_glsl_permutation_t *r_glsl_permutation;
994 /// storage for permutations linked in the hash table
995 memexpandablearray_t r_glsl_permutationarray;
996 
R_GLSL_FindPermutation(unsigned int mode,dpuint64 permutation)997 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
998 {
999 	//unsigned int hashdepth = 0;
1000 	unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1001 	r_glsl_permutation_t *p;
1002 	for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1003 	{
1004 		if (p->mode == mode && p->permutation == permutation)
1005 		{
1006 			//if (hashdepth > 10)
1007 			//	Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1008 			return p;
1009 		}
1010 		//hashdepth++;
1011 	}
1012 	p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1013 	p->mode = mode;
1014 	p->permutation = permutation;
1015 	p->hashnext = r_glsl_permutationhash[mode][hashindex];
1016 	r_glsl_permutationhash[mode][hashindex] = p;
1017 	//if (hashdepth > 10)
1018 	//	Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1019 	return p;
1020 }
1021 
R_ShaderStrCat(const char ** strings)1022 static char *R_ShaderStrCat(const char **strings)
1023 {
1024 	char *string, *s;
1025 	const char **p = strings;
1026 	const char *t;
1027 	size_t len = 0;
1028 	for (p = strings;(t = *p);p++)
1029 		len += strlen(t);
1030 	len++;
1031 	s = string = (char *)Mem_Alloc(r_main_mempool, len);
1032 	len = 0;
1033 	for (p = strings;(t = *p);p++)
1034 	{
1035 		len = strlen(t);
1036 		memcpy(s, t, len);
1037 		s += len;
1038 	}
1039 	*s = 0;
1040 	return string;
1041 }
1042 
1043 static char *R_ShaderStrCat(const char **strings);
R_InitShaderModeInfo(void)1044 static void R_InitShaderModeInfo(void)
1045 {
1046 	int i, language;
1047 	shadermodeinfo_t *modeinfo;
1048 	// we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1049 	for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1050 	{
1051 		for (i = 0; i < SHADERMODE_COUNT; i++)
1052 		{
1053 			char filename[MAX_QPATH];
1054 			modeinfo = &shadermodeinfo[language][i];
1055 			modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1056 			modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1057 			dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1058 			modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1059 		}
1060 	}
1061 }
1062 
ShaderModeInfo_GetShaderText(shadermodeinfo_t * modeinfo,qboolean printfromdisknotice,qboolean builtinonly)1063 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1064 {
1065 	char *shaderstring;
1066 	// if the mode has no filename we have to return the builtin string
1067 	if (builtinonly || !modeinfo->filename)
1068 		return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1069 	// note that FS_LoadFile appends a 0 byte to make it a valid string
1070 	shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1071 	if (shaderstring)
1072 	{
1073 		if (printfromdisknotice)
1074 			Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1075 		return shaderstring;
1076 	}
1077 	// fall back to builtinstring
1078 	return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1079 }
1080 
R_GLSL_CompilePermutation(r_glsl_permutation_t * p,unsigned int mode,dpuint64 permutation)1081 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1082 {
1083 	int i;
1084 	int ubibind;
1085 	int sampler;
1086 	shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1087 	char *sourcestring;
1088 	char permutationname[256];
1089 	int vertstrings_count = 0;
1090 	int geomstrings_count = 0;
1091 	int fragstrings_count = 0;
1092 	const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093 	const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094 	const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 
1096 	if (p->compiled)
1097 		return;
1098 	p->compiled = true;
1099 	p->program = 0;
1100 
1101 	permutationname[0] = 0;
1102 	sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1103 
1104 	strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1105 
1106 	// we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1107 	if(vid.support.glshaderversion >= 140)
1108 	{
1109 		vertstrings_list[vertstrings_count++] = "#version 140\n";
1110 		geomstrings_list[geomstrings_count++] = "#version 140\n";
1111 		fragstrings_list[fragstrings_count++] = "#version 140\n";
1112 		vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1113 		geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1114 		fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1115 	}
1116 	// if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1117 	else if(vid.support.glshaderversion >= 130)
1118 	{
1119 		vertstrings_list[vertstrings_count++] = "#version 130\n";
1120 		geomstrings_list[geomstrings_count++] = "#version 130\n";
1121 		fragstrings_list[fragstrings_count++] = "#version 130\n";
1122 		vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1123 		geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1124 		fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1125 	}
1126 	// if we can do #version 120, we should (this adds the invariant keyword)
1127 	else if(vid.support.glshaderversion >= 120)
1128 	{
1129 		vertstrings_list[vertstrings_count++] = "#version 120\n";
1130 		geomstrings_list[geomstrings_count++] = "#version 120\n";
1131 		fragstrings_list[fragstrings_count++] = "#version 120\n";
1132 		vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1133 		geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1134 		fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1135 	}
1136 	// GLES also adds several things from GLSL120
1137 	switch(vid.renderpath)
1138 	{
1139 	case RENDERPATH_GLES2:
1140 		vertstrings_list[vertstrings_count++] = "#define GLES\n";
1141 		geomstrings_list[geomstrings_count++] = "#define GLES\n";
1142 		fragstrings_list[fragstrings_count++] = "#define GLES\n";
1143 		break;
1144 	default:
1145 		break;
1146 	}
1147 
1148 	// the first pretext is which type of shader to compile as
1149 	// (later these will all be bound together as a program object)
1150 	vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1151 	geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1152 	fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1153 
1154 	// the second pretext is the mode (for example a light source)
1155 	vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1156 	geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1157 	fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1158 	strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1159 
1160 	// now add all the permutation pretexts
1161 	for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1162 	{
1163 		if (permutation & (1ll<<i))
1164 		{
1165 			vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1166 			geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1167 			fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1168 			strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1169 		}
1170 		else
1171 		{
1172 			// keep line numbers correct
1173 			vertstrings_list[vertstrings_count++] = "\n";
1174 			geomstrings_list[geomstrings_count++] = "\n";
1175 			fragstrings_list[fragstrings_count++] = "\n";
1176 		}
1177 	}
1178 
1179 	// add static parms
1180 	R_CompileShader_AddStaticParms(mode, permutation);
1181 	memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182 	vertstrings_count += shaderstaticparms_count;
1183 	memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184 	geomstrings_count += shaderstaticparms_count;
1185 	memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186 	fragstrings_count += shaderstaticparms_count;
1187 
1188 	// now append the shader text itself
1189 	vertstrings_list[vertstrings_count++] = sourcestring;
1190 	geomstrings_list[geomstrings_count++] = sourcestring;
1191 	fragstrings_list[fragstrings_count++] = sourcestring;
1192 
1193 	// compile the shader program
1194 	if (vertstrings_count + geomstrings_count + fragstrings_count)
1195 		p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1196 	if (p->program)
1197 	{
1198 		CHECKGLERROR
1199 		qglUseProgram(p->program);CHECKGLERROR
1200 		// look up all the uniform variable names we care about, so we don't
1201 		// have to look them up every time we set them
1202 
1203 #if 0
1204 		// debugging aid
1205 		{
1206 			GLint activeuniformindex = 0;
1207 			GLint numactiveuniforms = 0;
1208 			char uniformname[128];
1209 			GLsizei uniformnamelength = 0;
1210 			GLint uniformsize = 0;
1211 			GLenum uniformtype = 0;
1212 			memset(uniformname, 0, sizeof(uniformname));
1213 			qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1214 			Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1215 			for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1216 			{
1217 				qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1218 				Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1219 			}
1220 		}
1221 #endif
1222 
1223 		p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1224 		p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1225 		p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1226 		p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1227 		p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1228 		p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1229 		p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1230 		p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1231 		p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1232 		p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1233 		p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1234 		p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1235 		p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1236 		p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1237 		p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1238 		p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1239 		p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1240 		p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1241 		p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1242 		p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1243 		p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1244 		p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1245 		p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1246 		p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1247 		p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1248 		p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1249 		p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1250 		p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1251 		p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1252 		p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1253 		p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1254 		p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1255 		p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1256 		p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1257 		p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1258 		p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1259 		p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1260 		p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1261 		p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1262 		p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1263 		p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1264 		p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1265 		p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1266 		p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1267 		p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1268 		p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1269 		p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1270 		p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1271 		p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1272 		p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1273 		p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1274 		p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1275 		p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1276 		p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1277 		p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1278 		p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1279 		p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1280 		p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1281 		p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1282 		p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1283 		p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1284 		p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1285 		p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1286 		p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1287 		p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1288 		p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1289 		p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1290 		p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1291 		p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1292 		p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1293 		p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1294 		p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1295 		p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1296 		p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1297 		p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1298 		p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1299 		p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1300 		p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1301 		p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1302 		p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1303 		p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1304 		p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1305 		p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1306 		p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1307 		p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1308 		p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1309 		// initialize the samplers to refer to the texture units we use
1310 		p->tex_Texture_First = -1;
1311 		p->tex_Texture_Second = -1;
1312 		p->tex_Texture_GammaRamps = -1;
1313 		p->tex_Texture_Normal = -1;
1314 		p->tex_Texture_Color = -1;
1315 		p->tex_Texture_Gloss = -1;
1316 		p->tex_Texture_Glow = -1;
1317 		p->tex_Texture_SecondaryNormal = -1;
1318 		p->tex_Texture_SecondaryColor = -1;
1319 		p->tex_Texture_SecondaryGloss = -1;
1320 		p->tex_Texture_SecondaryGlow = -1;
1321 		p->tex_Texture_Pants = -1;
1322 		p->tex_Texture_Shirt = -1;
1323 		p->tex_Texture_FogHeightTexture = -1;
1324 		p->tex_Texture_FogMask = -1;
1325 		p->tex_Texture_Lightmap = -1;
1326 		p->tex_Texture_Deluxemap = -1;
1327 		p->tex_Texture_Attenuation = -1;
1328 		p->tex_Texture_Cube = -1;
1329 		p->tex_Texture_Refraction = -1;
1330 		p->tex_Texture_Reflection = -1;
1331 		p->tex_Texture_ShadowMap2D = -1;
1332 		p->tex_Texture_CubeProjection = -1;
1333 		p->tex_Texture_ScreenNormalMap = -1;
1334 		p->tex_Texture_ScreenDiffuse = -1;
1335 		p->tex_Texture_ScreenSpecular = -1;
1336 		p->tex_Texture_ReflectMask = -1;
1337 		p->tex_Texture_ReflectCube = -1;
1338 		p->tex_Texture_BounceGrid = -1;
1339 		// bind the texture samplers in use
1340 		sampler = 0;
1341 		if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1342 		if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1343 		if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1344 		if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1345 		if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1346 		if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1347 		if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1348 		if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1349 		if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1350 		if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1351 		if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1352 		if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1353 		if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1354 		if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1355 		if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1356 		if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1357 		if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1358 		if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1359 		if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1360 		if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1361 		if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1362 		if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1363 		if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1364 		if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1365 		if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1366 		if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1367 		if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1368 		if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1369 		if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1370 		// get the uniform block indices so we can bind them
1371 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1372 		if (vid.support.arb_uniform_buffer_object)
1373 			p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1374 		else
1375 #endif
1376 			p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1377 		// clear the uniform block bindings
1378 		p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1379 		// bind the uniform blocks in use
1380 		ubibind = 0;
1381 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1382 		if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1383 #endif
1384 		// we're done compiling and setting up the shader, at least until it is used
1385 		CHECKGLERROR
1386 		Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1387 	}
1388 	else
1389 		Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1390 
1391 	// free the strings
1392 	if (sourcestring)
1393 		Mem_Free(sourcestring);
1394 }
1395 
R_SetupShader_SetPermutationGLSL(unsigned int mode,dpuint64 permutation)1396 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1397 {
1398 	r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1399 	if (r_glsl_permutation != perm)
1400 	{
1401 		r_glsl_permutation = perm;
1402 		if (!r_glsl_permutation->program)
1403 		{
1404 			if (!r_glsl_permutation->compiled)
1405 			{
1406 				Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1407 				R_GLSL_CompilePermutation(perm, mode, permutation);
1408 			}
1409 			if (!r_glsl_permutation->program)
1410 			{
1411 				// remove features until we find a valid permutation
1412 				int i;
1413 				for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1414 				{
1415 					// reduce i more quickly whenever it would not remove any bits
1416 					dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1417 					if (!(permutation & j))
1418 						continue;
1419 					permutation -= j;
1420 					r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1421 					if (!r_glsl_permutation->compiled)
1422 						R_GLSL_CompilePermutation(perm, mode, permutation);
1423 					if (r_glsl_permutation->program)
1424 						break;
1425 				}
1426 				if (i >= SHADERPERMUTATION_COUNT)
1427 				{
1428 					//Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1429 					r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1430 					qglUseProgram(0);CHECKGLERROR
1431 					return; // no bit left to clear, entire mode is broken
1432 				}
1433 			}
1434 		}
1435 		CHECKGLERROR
1436 		qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1437 	}
1438 	if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1439 	if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1440 	if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1441 	CHECKGLERROR
1442 }
1443 
1444 #ifdef SUPPORTD3D
1445 
1446 #ifdef SUPPORTD3D
1447 #include <d3d9.h>
1448 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1449 extern D3DCAPS9 vid_d3d9caps;
1450 #endif
1451 
1452 struct r_hlsl_permutation_s;
1453 typedef struct r_hlsl_permutation_s
1454 {
1455 	/// hash lookup data
1456 	struct r_hlsl_permutation_s *hashnext;
1457 	unsigned int mode;
1458 	dpuint64 permutation;
1459 
1460 	/// indicates if we have tried compiling this permutation already
1461 	qboolean compiled;
1462 	/// NULL if compilation failed
1463 	IDirect3DVertexShader9 *vertexshader;
1464 	IDirect3DPixelShader9 *pixelshader;
1465 }
1466 r_hlsl_permutation_t;
1467 
1468 typedef enum D3DVSREGISTER_e
1469 {
1470 	D3DVSREGISTER_TexMatrix = 0, // float4x4
1471 	D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1472 	D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1473 	D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1474 	D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1475 	D3DVSREGISTER_ModelToLight = 20, // float4x4
1476 	D3DVSREGISTER_EyePosition = 24,
1477 	D3DVSREGISTER_FogPlane = 25,
1478 	D3DVSREGISTER_LightDir = 26,
1479 	D3DVSREGISTER_LightPosition = 27,
1480 }
1481 D3DVSREGISTER_t;
1482 
1483 typedef enum D3DPSREGISTER_e
1484 {
1485 	D3DPSREGISTER_Alpha = 0,
1486 	D3DPSREGISTER_BloomBlur_Parameters = 1,
1487 	D3DPSREGISTER_ClientTime = 2,
1488 	D3DPSREGISTER_Color_Ambient = 3,
1489 	D3DPSREGISTER_Color_Diffuse = 4,
1490 	D3DPSREGISTER_Color_Specular = 5,
1491 	D3DPSREGISTER_Color_Glow = 6,
1492 	D3DPSREGISTER_Color_Pants = 7,
1493 	D3DPSREGISTER_Color_Shirt = 8,
1494 	D3DPSREGISTER_DeferredColor_Ambient = 9,
1495 	D3DPSREGISTER_DeferredColor_Diffuse = 10,
1496 	D3DPSREGISTER_DeferredColor_Specular = 11,
1497 	D3DPSREGISTER_DeferredMod_Diffuse = 12,
1498 	D3DPSREGISTER_DeferredMod_Specular = 13,
1499 	D3DPSREGISTER_DistortScaleRefractReflect = 14,
1500 	D3DPSREGISTER_EyePosition = 15, // unused
1501 	D3DPSREGISTER_FogColor = 16,
1502 	D3DPSREGISTER_FogHeightFade = 17,
1503 	D3DPSREGISTER_FogPlane = 18,
1504 	D3DPSREGISTER_FogPlaneViewDist = 19,
1505 	D3DPSREGISTER_FogRangeRecip = 20,
1506 	D3DPSREGISTER_LightColor = 21,
1507 	D3DPSREGISTER_LightDir = 22, // unused
1508 	D3DPSREGISTER_LightPosition = 23,
1509 	D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1510 	D3DPSREGISTER_PixelSize = 25,
1511 	D3DPSREGISTER_ReflectColor = 26,
1512 	D3DPSREGISTER_ReflectFactor = 27,
1513 	D3DPSREGISTER_ReflectOffset = 28,
1514 	D3DPSREGISTER_RefractColor = 29,
1515 	D3DPSREGISTER_Saturation = 30,
1516 	D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1517 	D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1518 	D3DPSREGISTER_ScreenToDepth = 33,
1519 	D3DPSREGISTER_ShadowMap_Parameters = 34,
1520 	D3DPSREGISTER_ShadowMap_TextureScale = 35,
1521 	D3DPSREGISTER_SpecularPower = 36,
1522 	D3DPSREGISTER_UserVec1 = 37,
1523 	D3DPSREGISTER_UserVec2 = 38,
1524 	D3DPSREGISTER_UserVec3 = 39,
1525 	D3DPSREGISTER_UserVec4 = 40,
1526 	D3DPSREGISTER_ViewTintColor = 41,
1527 	D3DPSREGISTER_PixelToScreenTexCoord = 42,
1528 	D3DPSREGISTER_BloomColorSubtract = 43,
1529 	D3DPSREGISTER_ViewToLight = 44, // float4x4
1530 	D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1531 	D3DPSREGISTER_NormalmapScrollBlend = 52,
1532 	D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1533 	D3DPSREGISTER_OffsetMapping_Bias = 54,
1534 	// next at 54
1535 }
1536 D3DPSREGISTER_t;
1537 
1538 /// information about each possible shader permutation
1539 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1540 /// currently selected permutation
1541 r_hlsl_permutation_t *r_hlsl_permutation;
1542 /// storage for permutations linked in the hash table
1543 memexpandablearray_t r_hlsl_permutationarray;
1544 
R_HLSL_FindPermutation(unsigned int mode,dpuint64 permutation)1545 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1546 {
1547 	//unsigned int hashdepth = 0;
1548 	unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1549 	r_hlsl_permutation_t *p;
1550 	for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1551 	{
1552 		if (p->mode == mode && p->permutation == permutation)
1553 		{
1554 			//if (hashdepth > 10)
1555 			//	Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1556 			return p;
1557 		}
1558 		//hashdepth++;
1559 	}
1560 	p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1561 	p->mode = mode;
1562 	p->permutation = permutation;
1563 	p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1564 	r_hlsl_permutationhash[mode][hashindex] = p;
1565 	//if (hashdepth > 10)
1566 	//	Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1567 	return p;
1568 }
1569 
1570 #include <d3dx9.h>
1571 //#include <d3dx9shader.h>
1572 //#include <d3dx9mesh.h>
1573 
R_HLSL_CacheShader(r_hlsl_permutation_t * p,const char * cachename,const char * vertstring,const char * fragstring)1574 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1575 {
1576 	DWORD *vsbin = NULL;
1577 	DWORD *psbin = NULL;
1578 	fs_offset_t vsbinsize;
1579 	fs_offset_t psbinsize;
1580 //	IDirect3DVertexShader9 *vs = NULL;
1581 //	IDirect3DPixelShader9 *ps = NULL;
1582 	ID3DXBuffer *vslog = NULL;
1583 	ID3DXBuffer *vsbuffer = NULL;
1584 	ID3DXConstantTable *vsconstanttable = NULL;
1585 	ID3DXBuffer *pslog = NULL;
1586 	ID3DXBuffer *psbuffer = NULL;
1587 	ID3DXConstantTable *psconstanttable = NULL;
1588 	int vsresult = 0;
1589 	int psresult = 0;
1590 	char temp[MAX_INPUTLINE];
1591 	const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1592 	char vabuf[1024];
1593 	qboolean debugshader = gl_paranoid.integer != 0;
1594 	if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1595 	if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596 	if (!debugshader)
1597 	{
1598 		vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1599 		psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1600 	}
1601 	if ((!vsbin && vertstring) || (!psbin && fragstring))
1602 	{
1603 		const char* dllnames_d3dx9 [] =
1604 		{
1605 			"d3dx9_43.dll",
1606 			"d3dx9_42.dll",
1607 			"d3dx9_41.dll",
1608 			"d3dx9_40.dll",
1609 			"d3dx9_39.dll",
1610 			"d3dx9_38.dll",
1611 			"d3dx9_37.dll",
1612 			"d3dx9_36.dll",
1613 			"d3dx9_35.dll",
1614 			"d3dx9_34.dll",
1615 			"d3dx9_33.dll",
1616 			"d3dx9_32.dll",
1617 			"d3dx9_31.dll",
1618 			"d3dx9_30.dll",
1619 			"d3dx9_29.dll",
1620 			"d3dx9_28.dll",
1621 			"d3dx9_27.dll",
1622 			"d3dx9_26.dll",
1623 			"d3dx9_25.dll",
1624 			"d3dx9_24.dll",
1625 			NULL
1626 		};
1627 		dllhandle_t d3dx9_dll = NULL;
1628 		HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1629 		HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1630 		HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631 		dllfunction_t d3dx9_dllfuncs[] =
1632 		{
1633 			{"D3DXCompileShaderFromFileA",	(void **) &qD3DXCompileShaderFromFileA},
1634 			{"D3DXPreprocessShader",		(void **) &qD3DXPreprocessShader},
1635 			{"D3DXCompileShader",			(void **) &qD3DXCompileShader},
1636 			{NULL, NULL}
1637 		};
1638 		// 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...
1639 #ifndef ID3DXBuffer_GetBufferPointer
1640 #if !defined(__cplusplus) || defined(CINTERFACE)
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1643 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1644 #else
1645 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1646 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1647 #define ID3DXBuffer_Release(p)            (p)->Release()
1648 #endif
1649 #endif
1650 		if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1651 		{
1652 			DWORD shaderflags = 0;
1653 			if (debugshader)
1654 				shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1655 			vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1656 			psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1657 			if (vertstring && vertstring[0])
1658 			{
1659 				if (debugshader)
1660 				{
1661 					FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1662 					vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1663 				}
1664 				else
1665 					vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1666 				if (vsbuffer)
1667 				{
1668 					vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1669 					vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1670 					memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1671 					ID3DXBuffer_Release(vsbuffer);
1672 				}
1673 				if (vslog)
1674 				{
1675 					strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1676 					Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1677 					ID3DXBuffer_Release(vslog);
1678 				}
1679 			}
1680 			if (fragstring && fragstring[0])
1681 			{
1682 				if (debugshader)
1683 				{
1684 					FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1685 					psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1686 				}
1687 				else
1688 					psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1689 				if (psbuffer)
1690 				{
1691 					psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1692 					psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1693 					memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1694 					ID3DXBuffer_Release(psbuffer);
1695 				}
1696 				if (pslog)
1697 				{
1698 					strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1699 					Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1700 					ID3DXBuffer_Release(pslog);
1701 				}
1702 			}
1703 			Sys_UnloadLibrary(&d3dx9_dll);
1704 		}
1705 		else
1706 			Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1707 	}
1708 	if (vsbin && psbin)
1709 	{
1710 		vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1711 		if (FAILED(vsresult))
1712 			Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1713 		psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1714 		if (FAILED(psresult))
1715 			Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1716 	}
1717 	// free the shader data
1718 	vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1719 	psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1720 }
1721 
R_HLSL_CompilePermutation(r_hlsl_permutation_t * p,unsigned int mode,dpuint64 permutation)1722 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1723 {
1724 	int i;
1725 	shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1726 	int vertstring_length = 0;
1727 	int geomstring_length = 0;
1728 	int fragstring_length = 0;
1729 	char *t;
1730 	char *sourcestring;
1731 	char *vertstring, *geomstring, *fragstring;
1732 	char permutationname[256];
1733 	char cachename[256];
1734 	int vertstrings_count = 0;
1735 	int geomstrings_count = 0;
1736 	int fragstrings_count = 0;
1737 	const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1738 	const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739 	const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740 
1741 	if (p->compiled)
1742 		return;
1743 	p->compiled = true;
1744 	p->vertexshader = NULL;
1745 	p->pixelshader = NULL;
1746 
1747 	permutationname[0] = 0;
1748 	cachename[0] = 0;
1749 	sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1750 
1751 	strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1752 	strlcat(cachename, "hlsl/", sizeof(cachename));
1753 
1754 	// define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1755 	vertstrings_count = 0;
1756 	geomstrings_count = 0;
1757 	fragstrings_count = 0;
1758 	vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1759 	geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1760 	fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1761 
1762 	// the first pretext is which type of shader to compile as
1763 	// (later these will all be bound together as a program object)
1764 	vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1765 	geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1766 	fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1767 
1768 	// the second pretext is the mode (for example a light source)
1769 	vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1770 	geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1771 	fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1772 	strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1773 	strlcat(cachename, modeinfo->name, sizeof(cachename));
1774 
1775 	// now add all the permutation pretexts
1776 	for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777 	{
1778 		if (permutation & (1ll<<i))
1779 		{
1780 			vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1781 			geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1782 			fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1783 			strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1784 			strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1785 		}
1786 		else
1787 		{
1788 			// keep line numbers correct
1789 			vertstrings_list[vertstrings_count++] = "\n";
1790 			geomstrings_list[geomstrings_count++] = "\n";
1791 			fragstrings_list[fragstrings_count++] = "\n";
1792 		}
1793 	}
1794 
1795 	// add static parms
1796 	R_CompileShader_AddStaticParms(mode, permutation);
1797 	memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798 	vertstrings_count += shaderstaticparms_count;
1799 	memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800 	geomstrings_count += shaderstaticparms_count;
1801 	memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802 	fragstrings_count += shaderstaticparms_count;
1803 
1804 	// replace spaces in the cachename with _ characters
1805 	for (i = 0;cachename[i];i++)
1806 		if (cachename[i] == ' ')
1807 			cachename[i] = '_';
1808 
1809 	// now append the shader text itself
1810 	vertstrings_list[vertstrings_count++] = sourcestring;
1811 	geomstrings_list[geomstrings_count++] = sourcestring;
1812 	fragstrings_list[fragstrings_count++] = sourcestring;
1813 
1814 	vertstring_length = 0;
1815 	for (i = 0;i < vertstrings_count;i++)
1816 		vertstring_length += (int)strlen(vertstrings_list[i]);
1817 	vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1818 	for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1819 		memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1820 
1821 	geomstring_length = 0;
1822 	for (i = 0;i < geomstrings_count;i++)
1823 		geomstring_length += (int)strlen(geomstrings_list[i]);
1824 	geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1825 	for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1826 		memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1827 
1828 	fragstring_length = 0;
1829 	for (i = 0;i < fragstrings_count;i++)
1830 		fragstring_length += (int)strlen(fragstrings_list[i]);
1831 	fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1832 	for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1833 		memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1834 
1835 	// try to load the cached shader, or generate one
1836 	R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1837 
1838 	if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1839 		Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1840 	else
1841 		Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1842 
1843 	// free the strings
1844 	if (vertstring)
1845 		Mem_Free(vertstring);
1846 	if (geomstring)
1847 		Mem_Free(geomstring);
1848 	if (fragstring)
1849 		Mem_Free(fragstring);
1850 	if (sourcestring)
1851 		Mem_Free(sourcestring);
1852 }
1853 
hlslVSSetParameter16f(D3DVSREGISTER_t r,const float * a)1854 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
hlslVSSetParameter4fv(D3DVSREGISTER_t r,const float * a)1855 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
hlslVSSetParameter4f(D3DVSREGISTER_t r,float x,float y,float z,float w)1856 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);}
hlslVSSetParameter3f(D3DVSREGISTER_t r,float x,float y,float z)1857 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);}
hlslVSSetParameter2f(D3DVSREGISTER_t r,float x,float y)1858 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);}
hlslVSSetParameter1f(D3DVSREGISTER_t r,float x)1859 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);}
1860 
hlslPSSetParameter16f(D3DPSREGISTER_t r,const float * a)1861 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
hlslPSSetParameter4fv(D3DPSREGISTER_t r,const float * a)1862 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
hlslPSSetParameter4f(D3DPSREGISTER_t r,float x,float y,float z,float w)1863 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);}
hlslPSSetParameter3f(D3DPSREGISTER_t r,float x,float y,float z)1864 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);}
hlslPSSetParameter2f(D3DPSREGISTER_t r,float x,float y)1865 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);}
hlslPSSetParameter1f(D3DPSREGISTER_t r,float x)1866 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);}
1867 
R_SetupShader_SetPermutationHLSL(unsigned int mode,dpuint64 permutation)1868 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1869 {
1870 	r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1871 	if (r_hlsl_permutation != perm)
1872 	{
1873 		r_hlsl_permutation = perm;
1874 		if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875 		{
1876 			if (!r_hlsl_permutation->compiled)
1877 				R_HLSL_CompilePermutation(perm, mode, permutation);
1878 			if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1879 			{
1880 				// remove features until we find a valid permutation
1881 				int i;
1882 				for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883 				{
1884 					// reduce i more quickly whenever it would not remove any bits
1885 					dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1886 					if (!(permutation & j))
1887 						continue;
1888 					permutation -= j;
1889 					r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1890 					if (!r_hlsl_permutation->compiled)
1891 						R_HLSL_CompilePermutation(perm, mode, permutation);
1892 					if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1893 						break;
1894 				}
1895 				if (i >= SHADERPERMUTATION_COUNT)
1896 				{
1897 					//Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1898 					r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1899 					return; // no bit left to clear, entire mode is broken
1900 				}
1901 			}
1902 		}
1903 		IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1904 		IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1905 	}
1906 	hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1907 	hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1908 	hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1909 }
1910 #endif
1911 
R_SetupShader_SetPermutationSoft(unsigned int mode,dpuint64 permutation)1912 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1913 {
1914 	DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1915 	DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1916 	DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1917 	DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1918 }
1919 
R_GLSL_Restart_f(void)1920 void R_GLSL_Restart_f(void)
1921 {
1922 	unsigned int i, limit;
1923 	switch(vid.renderpath)
1924 	{
1925 	case RENDERPATH_D3D9:
1926 #ifdef SUPPORTD3D
1927 		{
1928 			r_hlsl_permutation_t *p;
1929 			r_hlsl_permutation = NULL;
1930 			limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1931 			for (i = 0;i < limit;i++)
1932 			{
1933 				if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1934 				{
1935 					if (p->vertexshader)
1936 						IDirect3DVertexShader9_Release(p->vertexshader);
1937 					if (p->pixelshader)
1938 						IDirect3DPixelShader9_Release(p->pixelshader);
1939 					Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1940 				}
1941 			}
1942 			memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1943 		}
1944 #endif
1945 		break;
1946 	case RENDERPATH_D3D10:
1947 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948 		break;
1949 	case RENDERPATH_D3D11:
1950 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951 		break;
1952 	case RENDERPATH_GL20:
1953 	case RENDERPATH_GLES2:
1954 		{
1955 			r_glsl_permutation_t *p;
1956 			r_glsl_permutation = NULL;
1957 			limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1958 			for (i = 0;i < limit;i++)
1959 			{
1960 				if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1961 				{
1962 					GL_Backend_FreeProgram(p->program);
1963 					Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1964 				}
1965 			}
1966 			memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1967 		}
1968 		break;
1969 	case RENDERPATH_GL11:
1970 	case RENDERPATH_GL13:
1971 	case RENDERPATH_GLES1:
1972 		break;
1973 	case RENDERPATH_SOFT:
1974 		break;
1975 	}
1976 }
1977 
R_GLSL_DumpShader_f(void)1978 static void R_GLSL_DumpShader_f(void)
1979 {
1980 	int i, language, mode, dupe;
1981 	char *text;
1982 	shadermodeinfo_t *modeinfo;
1983 	qfile_t *file;
1984 
1985 	for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1986 	{
1987 		modeinfo = shadermodeinfo[language];
1988 		for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1989 		{
1990 			// don't dump the same file multiple times (most or all shaders come from the same file)
1991 			for (dupe = mode - 1;dupe >= 0;dupe--)
1992 				if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1993 					break;
1994 			if (dupe >= 0)
1995 				continue;
1996 			text = modeinfo[mode].builtinstring;
1997 			if (!text)
1998 				continue;
1999 			file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2000 			if (file)
2001 			{
2002 				FS_Print(file, "/* The engine may define the following macros:\n");
2003 				FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2004 				for (i = 0;i < SHADERMODE_COUNT;i++)
2005 					FS_Print(file, modeinfo[i].pretext);
2006 				for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2007 					FS_Print(file, shaderpermutationinfo[i].pretext);
2008 				FS_Print(file, "*/\n");
2009 				FS_Print(file, text);
2010 				FS_Close(file);
2011 				Con_Printf("%s written\n", modeinfo[mode].filename);
2012 			}
2013 			else
2014 				Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2015 		}
2016 	}
2017 }
2018 
R_SetupShader_Generic(rtexture_t * first,rtexture_t * second,int texturemode,int rgbscale,qboolean usegamma,qboolean notrippy,qboolean suppresstexalpha)2019 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2020 {
2021 	dpuint64 permutation = 0;
2022 	if (r_trippy.integer && !notrippy)
2023 		permutation |= SHADERPERMUTATION_TRIPPY;
2024 	permutation |= SHADERPERMUTATION_VIEWTINT;
2025 	if (first)
2026 		permutation |= SHADERPERMUTATION_DIFFUSE;
2027 	if (second)
2028 		permutation |= SHADERPERMUTATION_SPECULAR;
2029 	if (texturemode == GL_MODULATE)
2030 		permutation |= SHADERPERMUTATION_COLORMAPPING;
2031 	else if (texturemode == GL_ADD)
2032 		permutation |= SHADERPERMUTATION_GLOW;
2033 	else if (texturemode == GL_DECAL)
2034 		permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2035 	if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2036 		permutation |= SHADERPERMUTATION_GAMMARAMPS;
2037 	if (suppresstexalpha)
2038 		permutation |= SHADERPERMUTATION_REFLECTCUBE;
2039 	if (!second)
2040 		texturemode = GL_MODULATE;
2041 	if (vid.allowalphatocoverage)
2042 		GL_AlphaToCoverage(false);
2043 	switch (vid.renderpath)
2044 	{
2045 	case RENDERPATH_D3D9:
2046 #ifdef SUPPORTD3D
2047 		R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2048 		R_Mesh_TexBind(GL20TU_FIRST , first );
2049 		R_Mesh_TexBind(GL20TU_SECOND, second);
2050 		if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2051 			R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2052 #endif
2053 		break;
2054 	case RENDERPATH_D3D10:
2055 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056 		break;
2057 	case RENDERPATH_D3D11:
2058 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059 		break;
2060 	case RENDERPATH_GL20:
2061 	case RENDERPATH_GLES2:
2062 		R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2063 		if (r_glsl_permutation->tex_Texture_First >= 0)
2064 			R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2065 		if (r_glsl_permutation->tex_Texture_Second >= 0)
2066 			R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2067 		if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2068 			R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2069 		break;
2070 	case RENDERPATH_GL13:
2071 	case RENDERPATH_GLES1:
2072 		R_Mesh_TexBind(0, first );
2073 		R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2074 		R_Mesh_TexMatrix(0, NULL);
2075 		R_Mesh_TexBind(1, second);
2076 		if (second)
2077 		{
2078 			R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2079 			R_Mesh_TexMatrix(1, NULL);
2080 		}
2081 		break;
2082 	case RENDERPATH_GL11:
2083 		R_Mesh_TexBind(0, first );
2084 		R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2085 		R_Mesh_TexMatrix(0, NULL);
2086 		break;
2087 	case RENDERPATH_SOFT:
2088 		R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2089 		R_Mesh_TexBind(GL20TU_FIRST , first );
2090 		R_Mesh_TexBind(GL20TU_SECOND, second);
2091 		break;
2092 	}
2093 }
2094 
R_SetupShader_Generic_NoTexture(qboolean usegamma,qboolean notrippy)2095 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2096 {
2097 	R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2098 }
2099 
R_SetupShader_DepthOrShadow(qboolean notrippy,qboolean depthrgb,qboolean skeletal)2100 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2101 {
2102 	dpuint64 permutation = 0;
2103 	if (r_trippy.integer && !notrippy)
2104 		permutation |= SHADERPERMUTATION_TRIPPY;
2105 	if (depthrgb)
2106 		permutation |= SHADERPERMUTATION_DEPTHRGB;
2107 	if (skeletal)
2108 		permutation |= SHADERPERMUTATION_SKELETAL;
2109 
2110 	if (vid.allowalphatocoverage)
2111 		GL_AlphaToCoverage(false);
2112 	switch (vid.renderpath)
2113 	{
2114 	case RENDERPATH_D3D9:
2115 #ifdef SUPPORTD3D
2116 		R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2117 #endif
2118 		break;
2119 	case RENDERPATH_D3D10:
2120 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2121 		break;
2122 	case RENDERPATH_D3D11:
2123 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2124 		break;
2125 	case RENDERPATH_GL20:
2126 	case RENDERPATH_GLES2:
2127 		R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2128 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2129 		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);
2130 #endif
2131 		break;
2132 	case RENDERPATH_GL13:
2133 	case RENDERPATH_GLES1:
2134 		R_Mesh_TexBind(0, 0);
2135 		R_Mesh_TexBind(1, 0);
2136 		break;
2137 	case RENDERPATH_GL11:
2138 		R_Mesh_TexBind(0, 0);
2139 		break;
2140 	case RENDERPATH_SOFT:
2141 		R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2142 		break;
2143 	}
2144 }
2145 
2146 extern qboolean r_shadow_usingdeferredprepass;
2147 extern rtexture_t *r_shadow_attenuationgradienttexture;
2148 extern rtexture_t *r_shadow_attenuation2dtexture;
2149 extern rtexture_t *r_shadow_attenuation3dtexture;
2150 extern qboolean r_shadow_usingshadowmap2d;
2151 extern qboolean r_shadow_usingshadowmaportho;
2152 extern float r_shadow_modelshadowmap_texturescale[4];
2153 extern float r_shadow_modelshadowmap_parameters[4];
2154 extern float r_shadow_lightshadowmap_texturescale[4];
2155 extern float r_shadow_lightshadowmap_parameters[4];
2156 extern qboolean r_shadow_shadowmapvsdct;
2157 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2159 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2160 extern matrix4x4_t r_shadow_shadowmapmatrix;
2161 extern int r_shadow_prepass_width;
2162 extern int r_shadow_prepass_height;
2163 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2164 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2165 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2166 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2167 
2168 #define BLENDFUNC_ALLOWS_COLORMOD      1
2169 #define BLENDFUNC_ALLOWS_FOG           2
2170 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2171 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2172 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
R_BlendFuncFlags(int src,int dst)2173 static int R_BlendFuncFlags(int src, int dst)
2174 {
2175 	int r = 0;
2176 
2177 	// a blendfunc allows colormod if:
2178 	// a) it can never keep the destination pixel invariant, or
2179 	// b) it can keep the destination pixel invariant, and still can do so if colormodded
2180 	// this is to prevent unintended side effects from colormod
2181 
2182 	// a blendfunc allows fog if:
2183 	// blend(fog(src), fog(dst)) == fog(blend(src, dst))
2184 	// this is to prevent unintended side effects from fog
2185 
2186 	// these checks are the output of fogeval.pl
2187 
2188 	r |= BLENDFUNC_ALLOWS_COLORMOD;
2189 	if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190 	if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191 	if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192 	if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2193 	if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194 	if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195 	if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196 	if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197 	if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2198 	if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2199 	if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200 	if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2201 	if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2202 	if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203 	if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204 	if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2205 	if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206 	if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2207 	if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2208 	if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2209 	if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2210 
2211 	return r;
2212 }
2213 
R_SetupShader_Surface(const float rtlightambient[3],const float rtlightdiffuse[3],const float rtlightspecular[3],rsurfacepass_t rsurfacepass,int texturenumsurfaces,const msurface_t ** texturesurfacelist,void * surfacewaterplane,qboolean notrippy)2214 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2215 {
2216 	// select a permutation of the lighting shader appropriate to this
2217 	// combination of texture, entity, light source, and fogging, only use the
2218 	// minimum features necessary to avoid wasting rendering time in the
2219 	// fragment shader on features that are not being used
2220 	dpuint64 permutation = 0;
2221 	unsigned int mode = 0;
2222 	int blendfuncflags;
2223 	texture_t *t = rsurface.texture;
2224 	float m16f[16];
2225 	matrix4x4_t tempmatrix;
2226 	r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2227 	if (r_trippy.integer && !notrippy)
2228 		permutation |= SHADERPERMUTATION_TRIPPY;
2229 	if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2230 		permutation |= SHADERPERMUTATION_ALPHAKILL;
2231 	if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2232 		permutation |= SHADERPERMUTATION_OCCLUDE;
2233 	if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2234 		permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2235 	if (rsurfacepass == RSURFPASS_BACKGROUND)
2236 	{
2237 		// distorted background
2238 		if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2239 		{
2240 			mode = SHADERMODE_WATER;
2241 			if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2242 				permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2243 			if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2244 			{
2245 				// this is the right thing to do for wateralpha
2246 				GL_BlendFunc(GL_ONE, GL_ZERO);
2247 				blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2248 			}
2249 			else
2250 			{
2251 				// this is the right thing to do for entity alpha
2252 				GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253 				blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254 			}
2255 		}
2256 		else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2257 		{
2258 			mode = SHADERMODE_REFRACTION;
2259 			if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2260 				permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2261 			GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262 			blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263 		}
2264 		else
2265 		{
2266 			mode = SHADERMODE_GENERIC;
2267 			permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2268 			GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2269 			blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2270 		}
2271 		if (vid.allowalphatocoverage)
2272 			GL_AlphaToCoverage(false);
2273 	}
2274 	else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2275 	{
2276 		if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2277 		{
2278 			switch(t->offsetmapping)
2279 			{
2280 			case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281 			case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282 			case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283 			case OFFSETMAPPING_OFF: break;
2284 			}
2285 		}
2286 		if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287 			permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288 		// normalmap (deferred prepass), may use alpha test on diffuse
2289 		mode = SHADERMODE_DEFERREDGEOMETRY;
2290 		GL_BlendFunc(GL_ONE, GL_ZERO);
2291 		blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2292 		if (vid.allowalphatocoverage)
2293 			GL_AlphaToCoverage(false);
2294 	}
2295 	else if (rsurfacepass == RSURFPASS_RTLIGHT)
2296 	{
2297 		if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2298 		{
2299 			switch(t->offsetmapping)
2300 			{
2301 			case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302 			case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303 			case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304 			case OFFSETMAPPING_OFF: break;
2305 			}
2306 		}
2307 		if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308 			permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309 		if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2310 			permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2311 		// light source
2312 		mode = SHADERMODE_LIGHTSOURCE;
2313 		if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2314 			permutation |= SHADERPERMUTATION_CUBEFILTER;
2315 		if (VectorLength2(rtlightdiffuse) > 0)
2316 			permutation |= SHADERPERMUTATION_DIFFUSE;
2317 		if (VectorLength2(rtlightspecular) > 0)
2318 			permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2319 		if (r_refdef.fogenabled)
2320 			permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321 		if (t->colormapping)
2322 			permutation |= SHADERPERMUTATION_COLORMAPPING;
2323 		if (r_shadow_usingshadowmap2d)
2324 		{
2325 			permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2326 			if(r_shadow_shadowmapvsdct)
2327 				permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2328 
2329 			if (r_shadow_shadowmap2ddepthbuffer)
2330 				permutation |= SHADERPERMUTATION_DEPTHRGB;
2331 		}
2332 		if (t->reflectmasktexture)
2333 			permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334 		GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2335 		blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2336 		if (vid.allowalphatocoverage)
2337 			GL_AlphaToCoverage(false);
2338 	}
2339 	else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2340 	{
2341 		if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2342 		{
2343 			switch(t->offsetmapping)
2344 			{
2345 			case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2346 			case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347 			case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348 			case OFFSETMAPPING_OFF: break;
2349 			}
2350 		}
2351 		if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2352 			permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353 		if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2354 			permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2355 		// directional model lighting
2356 		mode = SHADERMODE_LIGHTDIRECTION;
2357 		if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358 			permutation |= SHADERPERMUTATION_GLOW;
2359 		if (VectorLength2(t->render_modellight_diffuse))
2360 			permutation |= SHADERPERMUTATION_DIFFUSE;
2361 		if (VectorLength2(t->render_modellight_specular) > 0)
2362 			permutation |= SHADERPERMUTATION_SPECULAR;
2363 		if (r_refdef.fogenabled)
2364 			permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365 		if (t->colormapping)
2366 			permutation |= SHADERPERMUTATION_COLORMAPPING;
2367 		if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368 		{
2369 			permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370 			permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371 
2372 			if (r_shadow_shadowmap2ddepthbuffer)
2373 				permutation |= SHADERPERMUTATION_DEPTHRGB;
2374 		}
2375 		if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 			permutation |= SHADERPERMUTATION_REFLECTION;
2377 		if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2378 			permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379 		if (t->reflectmasktexture)
2380 			permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381 		if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2382 		{
2383 			permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384 			if (r_shadow_bouncegrid_state.directional)
2385 				permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386 		}
2387 		GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2388 		blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389 		// when using alphatocoverage, we don't need alphakill
2390 		if (vid.allowalphatocoverage)
2391 		{
2392 			if (r_transparent_alphatocoverage.integer)
2393 			{
2394 				GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395 				permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396 			}
2397 			else
2398 				GL_AlphaToCoverage(false);
2399 		}
2400 	}
2401 	else
2402 	{
2403 		if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2404 		{
2405 			switch(t->offsetmapping)
2406 			{
2407 			case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408 			case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409 			case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410 			case OFFSETMAPPING_OFF: break;
2411 			}
2412 		}
2413 		if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414 			permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415 		if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416 			permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2417 		// lightmapped wall
2418 		if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419 			permutation |= SHADERPERMUTATION_GLOW;
2420 		if (r_refdef.fogenabled)
2421 			permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422 		if (t->colormapping)
2423 			permutation |= SHADERPERMUTATION_COLORMAPPING;
2424 		if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425 		{
2426 			permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427 			permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428 
2429 			if (r_shadow_shadowmap2ddepthbuffer)
2430 				permutation |= SHADERPERMUTATION_DEPTHRGB;
2431 		}
2432 		if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433 			permutation |= SHADERPERMUTATION_REFLECTION;
2434 		if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2435 			permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436 		if (t->reflectmasktexture)
2437 			permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438 		if (FAKELIGHT_ENABLED)
2439 		{
2440 			// fake lightmapping (q1bsp, q3bsp, fullbright map)
2441 			mode = SHADERMODE_FAKELIGHT;
2442 			permutation |= SHADERPERMUTATION_DIFFUSE;
2443 			if (VectorLength2(t->render_lightmap_specular) > 0)
2444 				permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445 		}
2446 		else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447 		{
2448 			// deluxemapping (light direction texture)
2449 			if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450 				mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451 			else
2452 				mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453 			permutation |= SHADERPERMUTATION_DIFFUSE;
2454 			if (VectorLength2(t->render_lightmap_specular) > 0)
2455 				permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456 		}
2457 		else if (r_glsl_deluxemapping.integer >= 2)
2458 		{
2459 			// fake deluxemapping (uniform light direction in tangentspace)
2460 			if (rsurface.uselightmaptexture)
2461 				mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462 			else
2463 				mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464 			permutation |= SHADERPERMUTATION_DIFFUSE;
2465 			if (VectorLength2(t->render_lightmap_specular) > 0)
2466 				permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467 		}
2468 		else if (rsurface.uselightmaptexture)
2469 		{
2470 			// ordinary lightmapping (q1bsp, q3bsp)
2471 			mode = SHADERMODE_LIGHTMAP;
2472 		}
2473 		else
2474 		{
2475 			// ordinary vertex coloring (q3bsp)
2476 			mode = SHADERMODE_VERTEXCOLOR;
2477 		}
2478 		if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2479 		{
2480 			permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481 			if (r_shadow_bouncegrid_state.directional)
2482 				permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483 		}
2484 		GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2485 		blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486 		// when using alphatocoverage, we don't need alphakill
2487 		if (vid.allowalphatocoverage)
2488 		{
2489 			if (r_transparent_alphatocoverage.integer)
2490 			{
2491 				GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492 				permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493 			}
2494 			else
2495 				GL_AlphaToCoverage(false);
2496 		}
2497 	}
2498 	if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499 		permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500 	if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501 		permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502 	switch(vid.renderpath)
2503 	{
2504 	case RENDERPATH_D3D9:
2505 #ifdef SUPPORTD3D
2506 		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);
2507 		R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2508 		R_SetupShader_SetPermutationHLSL(mode, permutation);
2509 		Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510 		if (mode == SHADERMODE_LIGHTSOURCE)
2511 		{
2512 			Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513 			hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2514 		}
2515 		else
2516 		{
2517 			if (mode == SHADERMODE_LIGHTDIRECTION)
2518 			{
2519 				hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2520 			}
2521 		}
2522 		Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523 		Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524 		Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525 		hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526 		hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527 
2528 		if (mode == SHADERMODE_LIGHTSOURCE)
2529 		{
2530 			hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531 			hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2532 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2533 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2534 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2535 
2536 			// additive passes are only darkened by fog, not tinted
2537 			hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538 			hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2539 		}
2540 		else
2541 		{
2542 			hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2543 			hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2544 			if (mode == SHADERMODE_FLATCOLOR)
2545 			{
2546 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2547 			}
2548 			else if (mode == SHADERMODE_LIGHTDIRECTION)
2549 			{
2550 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2551 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2552 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2553 				hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2554 				hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2555 			}
2556 			else
2557 			{
2558 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2559 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2560 				hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2561 			}
2562 			// additive passes are only darkened by fog, not tinted
2563 			if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2564 				hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2565 			else
2566 				hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2567 			hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2568 			hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2569 			hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2570 			hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2571 			hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2572 			hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2573 			hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2574 			hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2575 			if (mode == SHADERMODE_WATER)
2576 				hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2577 		}
2578 		if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2579 		{
2580 			hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2581 			hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2582 		}
2583 		else
2584 		{
2585 			hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2586 			hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2587 		}
2588 		hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2589 		hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2590 		hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2591 		if (t->pantstexture)
2592 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2593 		else
2594 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2595 		if (t->shirttexture)
2596 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2597 		else
2598 			hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2599 		hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2600 		hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2601 		hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2602 		hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2603 		hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2604 				r_glsl_offsetmapping_scale.value*t->offsetscale,
2605 				max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606 				1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607 				max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2608 			);
2609 		hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2610 		hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2611 		hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2612 		hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2613 
2614 		R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2615 		R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2616 		R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2617 		R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2618 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2619 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2620 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2621 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2622 		if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2623 		if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2624 		if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2625 		if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2626 		if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2627 		if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2628 		R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2629 		R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2630 		if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2631 		if (rsurfacepass == RSURFPASS_BACKGROUND)
2632 		{
2633 			R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2634 			if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2635 			R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636 		}
2637 		else
2638 		{
2639 			if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2640 		}
2641 //		if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2642 		if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2643 		if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2644 		if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2645 		{
2646 			R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2647 			if (rsurface.rtlight)
2648 			{
2649 				if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2650 				if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2651 			}
2652 		}
2653 #endif
2654 		break;
2655 	case RENDERPATH_D3D10:
2656 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657 		break;
2658 	case RENDERPATH_D3D11:
2659 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2660 		break;
2661 	case RENDERPATH_GL20:
2662 	case RENDERPATH_GLES2:
2663 		if (!vid.useinterleavedarrays)
2664 		{
2665 			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);
2666 			R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2667 			R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2668 			R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2669 			R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2670 			R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2671 			R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2672 			R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2673 			R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2674 			R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2675 			R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2676 		}
2677 		else
2678 		{
2679 			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);
2680 			R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2681 		}
2682 		// this has to be after RSurf_PrepareVerticesForBatch
2683 		if (rsurface.batchskeletaltransform3x4buffer)
2684 			permutation |= SHADERPERMUTATION_SKELETAL;
2685 		R_SetupShader_SetPermutationGLSL(mode, permutation);
2686 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2687 		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);
2688 #endif
2689 		if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2690 		if (mode == SHADERMODE_LIGHTSOURCE)
2691 		{
2692 			if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2693 			if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2694 			if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2695 			if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2696 			if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2697 			if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2698 
2699 			// additive passes are only darkened by fog, not tinted
2700 			if (r_glsl_permutation->loc_FogColor >= 0)
2701 				qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2702 			if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2703 		}
2704 		else
2705 		{
2706 			if (mode == SHADERMODE_FLATCOLOR)
2707 			{
2708 				if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2709 			}
2710 			else if (mode == SHADERMODE_LIGHTDIRECTION)
2711 			{
2712 				if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2713 				if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2714 				if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2715 				if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2716 				if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2717 				if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2718 				if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2719 			}
2720 			else
2721 			{
2722 				if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2723 				if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2724 				if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2725 				if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2726 				if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2727 			}
2728 			// additive passes are only darkened by fog, not tinted
2729 			if (r_glsl_permutation->loc_FogColor >= 0)
2730 			{
2731 				if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2732 					qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2733 				else
2734 					qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2735 			}
2736 			if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2737 			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]);
2738 			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]);
2739 			if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2740 			if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2741 			if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2742 			if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2743 			if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2744 			if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2745 		}
2746 		if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2747 		if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2748 		if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2749 		if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2750 		{
2751 			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]);
2752 			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]);
2753 		}
2754 		else
2755 		{
2756 			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]);
2757 			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]);
2758 		}
2759 
2760 		if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2761 		if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2762 		if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2763 		if (r_glsl_permutation->loc_Color_Pants >= 0)
2764 		{
2765 			if (t->pantstexture)
2766 				qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2767 			else
2768 				qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2769 		}
2770 		if (r_glsl_permutation->loc_Color_Shirt >= 0)
2771 		{
2772 			if (t->shirttexture)
2773 				qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2774 			else
2775 				qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2776 		}
2777 		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]);
2778 		if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2779 		if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2780 		if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2781 		if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2782 				r_glsl_offsetmapping_scale.value*t->offsetscale,
2783 				max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2784 				1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785 				max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2786 			);
2787 		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);
2788 		if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2789 		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]);
2790 		if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2791 		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);}
2792 		if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2793 
2794 		if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2795 		if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2796 		if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2797 		if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2798 		if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2799 		if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2800 		if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2801 		if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2802 		if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2803 		if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2804 		if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2805 		if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2806 		if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2807 		if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2808 		if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2809 		if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2810 		if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2811 		if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812 		if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813 		if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2814 		if (rsurfacepass == RSURFPASS_BACKGROUND)
2815 		{
2816 			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);
2817 			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);
2818 			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);
2819 		}
2820 		else
2821 		{
2822 			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);
2823 		}
2824 		if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2825 		if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2826 		if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2827 		if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2828 		{
2829 			if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2830 			if (rsurface.rtlight)
2831 			{
2832 				if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2833 				if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2834 			}
2835 		}
2836 		if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2837 		CHECKGLERROR
2838 		break;
2839 	case RENDERPATH_GL11:
2840 	case RENDERPATH_GL13:
2841 	case RENDERPATH_GLES1:
2842 		break;
2843 	case RENDERPATH_SOFT:
2844 		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);
2845 		R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2846 		R_SetupShader_SetPermutationSoft(mode, permutation);
2847 		{Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2848 		if (mode == SHADERMODE_LIGHTSOURCE)
2849 		{
2850 			{Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2851 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2852 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2853 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2854 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2855 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2856 
2857 			// additive passes are only darkened by fog, not tinted
2858 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2859 			DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2860 		}
2861 		else
2862 		{
2863 			if (mode == SHADERMODE_FLATCOLOR)
2864 			{
2865 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2866 			}
2867 			else if (mode == SHADERMODE_LIGHTDIRECTION)
2868 			{
2869 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2870 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2871 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2872 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2873 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2874 			}
2875 			else
2876 			{
2877 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2878 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2879 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2880 			}
2881 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2882 			DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2883 			// additive passes are only darkened by fog, not tinted
2884 			if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2885 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2886 			else
2887 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2888 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2889 			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]);
2890 			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]);
2891 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2892 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2893 			DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2894 			DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2895 			DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896 			DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2897 		}
2898 		{Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2899 		{Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2900 		{Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2901 		if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2902 		{
2903 			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]);
2904 			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]);
2905 		}
2906 		else
2907 		{
2908 			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]);
2909 			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]);
2910 		}
2911 
2912 		DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2913 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2914 		DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915 		if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916 		{
2917 			if (t->pantstexture)
2918 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2919 			else
2920 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921 		}
2922 		if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923 		{
2924 			if (t->shirttexture)
2925 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2926 			else
2927 				DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928 		}
2929 		DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933 		DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934 				r_glsl_offsetmapping_scale.value*t->offsetscale,
2935 				max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936 				1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937 				max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938 			);
2939 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940 		DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2941 		DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942 		DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943 
2944 		R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2945 		R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2946 		R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2947 		R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2948 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2949 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2950 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2951 		if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2952 		if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2953 		if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2954 		if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2955 		if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2956 		if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957 		if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958 		R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959 		R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960 		if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961 		if (rsurfacepass == RSURFPASS_BACKGROUND)
2962 		{
2963 			R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964 			if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965 			R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966 		}
2967 		else
2968 		{
2969 			if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970 		}
2971 //		if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972 		if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973 		if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974 		if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975 		{
2976 			R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977 			if (rsurface.rtlight)
2978 			{
2979 				if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980 				if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981 			}
2982 		}
2983 		break;
2984 	}
2985 }
2986 
R_SetupShader_DeferredLight(const rtlight_t * rtlight)2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989 	// select a permutation of the lighting shader appropriate to this
2990 	// combination of texture, entity, light source, and fogging, only use the
2991 	// minimum features necessary to avoid wasting rendering time in the
2992 	// fragment shader on features that are not being used
2993 	dpuint64 permutation = 0;
2994 	unsigned int mode = 0;
2995 	const float *lightcolorbase = rtlight->currentcolor;
2996 	float ambientscale = rtlight->ambientscale;
2997 	float diffusescale = rtlight->diffusescale;
2998 	float specularscale = rtlight->specularscale;
2999 	// this is the location of the light in view space
3000 	vec3_t viewlightorigin;
3001 	// this transforms from view space (camera) to light space (cubemap)
3002 	matrix4x4_t viewtolight;
3003 	matrix4x4_t lighttoview;
3004 	float viewtolight16f[16];
3005 	// light source
3006 	mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007 	if (rtlight->currentcubemap != r_texture_whitecube)
3008 		permutation |= SHADERPERMUTATION_CUBEFILTER;
3009 	if (diffusescale > 0)
3010 		permutation |= SHADERPERMUTATION_DIFFUSE;
3011 	if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012 		permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013 	if (r_shadow_usingshadowmap2d)
3014 	{
3015 		permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016 		if (r_shadow_shadowmapvsdct)
3017 			permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018 
3019 		if (r_shadow_shadowmap2ddepthbuffer)
3020 			permutation |= SHADERPERMUTATION_DEPTHRGB;
3021 	}
3022 	if (vid.allowalphatocoverage)
3023 		GL_AlphaToCoverage(false);
3024 	Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025 	Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026 	Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3027 	Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028 	switch(vid.renderpath)
3029 	{
3030 	case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032 		R_SetupShader_SetPermutationHLSL(mode, permutation);
3033 		hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034 		hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035 		hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036 		hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037 		hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038 		hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3039 		hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3040 		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);
3041 		hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042 		hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043 
3044 		R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045 		R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046 		R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047 		R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048 		R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050 		break;
3051 	case RENDERPATH_D3D10:
3052 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053 		break;
3054 	case RENDERPATH_D3D11:
3055 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056 		break;
3057 	case RENDERPATH_GL20:
3058 	case RENDERPATH_GLES2:
3059 		R_SetupShader_SetPermutationGLSL(mode, permutation);
3060 		if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061 		if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062 		if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063 		if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064 		if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065 		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]);
3066 		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]);
3067 		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);
3068 		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]);
3069 		if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070 
3071 		if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072 		if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073 		if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074 		if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075 		if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076 		break;
3077 	case RENDERPATH_GL11:
3078 	case RENDERPATH_GL13:
3079 	case RENDERPATH_GLES1:
3080 		break;
3081 	case RENDERPATH_SOFT:
3082 		R_SetupShader_SetPermutationGLSL(mode, permutation);
3083 		DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084 		DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085 		DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086 		DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087 		DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088 		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]);
3089 		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]);
3090 		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);
3091 		DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092 		DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093 
3094 		R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095 		R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096 		R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097 		R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098 		R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099 		break;
3100 	}
3101 }
3102 
3103 #define SKINFRAME_HASH 1024
3104 
3105 typedef struct
3106 {
3107 	unsigned int loadsequence; // incremented each level change
3108 	memexpandablearray_t array;
3109 	skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113 
R_SkinFrame_PrepareForPurge(void)3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116 	r_skinframe.loadsequence++;
3117 	// wrap it without hitting zero
3118 	if (r_skinframe.loadsequence >= 200)
3119 		r_skinframe.loadsequence = 1;
3120 }
3121 
R_SkinFrame_MarkUsed(skinframe_t * skinframe)3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124 	if (!skinframe)
3125 		return;
3126 	// mark the skinframe as used for the purging code
3127 	skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129 
R_SkinFrame_PurgeSkinFrame(skinframe_t * s)3130 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3131 {
3132 	if (s->merged == s->base)
3133 		s->merged = NULL;
3134 	R_PurgeTexture(s->stain); s->stain = NULL;
3135 	R_PurgeTexture(s->merged); s->merged = NULL;
3136 	R_PurgeTexture(s->base); s->base = NULL;
3137 	R_PurgeTexture(s->pants); s->pants = NULL;
3138 	R_PurgeTexture(s->shirt); s->shirt = NULL;
3139 	R_PurgeTexture(s->nmap); s->nmap = NULL;
3140 	R_PurgeTexture(s->gloss); s->gloss = NULL;
3141 	R_PurgeTexture(s->glow); s->glow = NULL;
3142 	R_PurgeTexture(s->fog); s->fog = NULL;
3143 	R_PurgeTexture(s->reflect); s->reflect = NULL;
3144 	s->loadsequence = 0;
3145 }
3146 
R_SkinFrame_Purge(void)3147 void R_SkinFrame_Purge(void)
3148 {
3149 	int i;
3150 	skinframe_t *s;
3151 	for (i = 0;i < SKINFRAME_HASH;i++)
3152 	{
3153 		for (s = r_skinframe.hash[i];s;s = s->next)
3154 		{
3155 			if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3156 				R_SkinFrame_PurgeSkinFrame(s);
3157 		}
3158 	}
3159 }
3160 
R_SkinFrame_FindNextByName(skinframe_t * last,const char * name)3161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3162 	skinframe_t *item;
3163 	char basename[MAX_QPATH];
3164 
3165 	Image_StripImageExtension(name, basename, sizeof(basename));
3166 
3167 	if( last == NULL ) {
3168 		int hashindex;
3169 		hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170 		item = r_skinframe.hash[hashindex];
3171 	} else {
3172 		item = last->next;
3173 	}
3174 
3175 	// linearly search through the hash bucket
3176 	for( ; item ; item = item->next ) {
3177 		if( !strcmp( item->basename, basename ) ) {
3178 			return item;
3179 		}
3180 	}
3181 	return NULL;
3182 }
3183 
R_SkinFrame_Find(const char * name,int textureflags,int comparewidth,int compareheight,int comparecrc,qboolean add)3184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3185 {
3186 	skinframe_t *item;
3187 	int hashindex;
3188 	char basename[MAX_QPATH];
3189 
3190 	Image_StripImageExtension(name, basename, sizeof(basename));
3191 
3192 	hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3193 	for (item = r_skinframe.hash[hashindex];item;item = item->next)
3194 		if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3195 			break;
3196 
3197 	if (!item)
3198 	{
3199 		if (!add)
3200 			return NULL;
3201 		item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202 		memset(item, 0, sizeof(*item));
3203 		strlcpy(item->basename, basename, sizeof(item->basename));
3204 		item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205 		item->comparewidth = comparewidth;
3206 		item->compareheight = compareheight;
3207 		item->comparecrc = comparecrc;
3208 		item->next = r_skinframe.hash[hashindex];
3209 		r_skinframe.hash[hashindex] = item;
3210 	}
3211 	else if (textureflags & TEXF_FORCE_RELOAD)
3212 	{
3213 		if (!add)
3214 			return NULL;
3215 		R_SkinFrame_PurgeSkinFrame(item);
3216 	}
3217 
3218 	R_SkinFrame_MarkUsed(item);
3219 	return item;
3220 }
3221 
3222 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3223 	{ \
3224 		unsigned long long avgcolor[5], wsum; \
3225 		int pix, comp, w; \
3226 		avgcolor[0] = 0; \
3227 		avgcolor[1] = 0; \
3228 		avgcolor[2] = 0; \
3229 		avgcolor[3] = 0; \
3230 		avgcolor[4] = 0; \
3231 		wsum = 0; \
3232 		for(pix = 0; pix < cnt; ++pix) \
3233 		{ \
3234 			w = 0; \
3235 			for(comp = 0; comp < 3; ++comp) \
3236 				w += getpixel; \
3237 			if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3238 			{ \
3239 				++wsum; \
3240 				/* comp = 3; -- not needed, comp is always 3 when we get here */ \
3241 				w = getpixel; \
3242 				for(comp = 0; comp < 3; ++comp) \
3243 					avgcolor[comp] += getpixel * w; \
3244 				avgcolor[3] += w; \
3245 			} \
3246 			/* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247 			avgcolor[4] += getpixel; \
3248 		} \
3249 		if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3250 			avgcolor[3] = 1; \
3251 		skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3252 		skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3253 		skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3254 		skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3255 	}
3256 
3257 extern cvar_t gl_picmip;
R_SkinFrame_LoadExternal(const char * name,int textureflags,qboolean complain,qboolean fallbacknotexture)3258 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3259 {
3260 	int j;
3261 	unsigned char *pixels;
3262 	unsigned char *bumppixels;
3263 	unsigned char *basepixels = NULL;
3264 	int basepixels_width = 0;
3265 	int basepixels_height = 0;
3266 	skinframe_t *skinframe;
3267 	rtexture_t *ddsbase = NULL;
3268 	qboolean ddshasalpha = false;
3269 	float ddsavgcolor[4];
3270 	char basename[MAX_QPATH];
3271 	int miplevel = R_PicmipForFlags(textureflags);
3272 	int savemiplevel = miplevel;
3273 	int mymiplevel;
3274 	char vabuf[1024];
3275 
3276 	if (cls.state == ca_dedicated)
3277 		return NULL;
3278 
3279 	// return an existing skinframe if already loaded
3280 	// if loading of the first image fails, don't make a new skinframe as it
3281 	// would cause all future lookups of this to be missing
3282 	skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3283 	if (skinframe && skinframe->base)
3284 		return skinframe;
3285 
3286 	Image_StripImageExtension(name, basename, sizeof(basename));
3287 
3288 	// check for DDS texture file first
3289 	if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3290 	{
3291 		basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3292 		if (basepixels == NULL && fallbacknotexture)
3293 			basepixels = Image_GenerateNoTexture();
3294 		if (basepixels == NULL)
3295 			return NULL;
3296 	}
3297 
3298 	// FIXME handle miplevel
3299 
3300 	if (developer_loading.integer)
3301 		Con_Printf("loading skin \"%s\"\n", name);
3302 
3303 	// we've got some pixels to store, so really allocate this new texture now
3304 	if (!skinframe)
3305 		skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3306 	textureflags &= ~TEXF_FORCE_RELOAD;
3307 	skinframe->stain = NULL;
3308 	skinframe->merged = NULL;
3309 	skinframe->base = NULL;
3310 	skinframe->pants = NULL;
3311 	skinframe->shirt = NULL;
3312 	skinframe->nmap = NULL;
3313 	skinframe->gloss = NULL;
3314 	skinframe->glow = NULL;
3315 	skinframe->fog = NULL;
3316 	skinframe->reflect = NULL;
3317 	skinframe->hasalpha = false;
3318 	// we could store the q2animname here too
3319 
3320 	if (ddsbase)
3321 	{
3322 		skinframe->base = ddsbase;
3323 		skinframe->hasalpha = ddshasalpha;
3324 		VectorCopy(ddsavgcolor, skinframe->avgcolor);
3325 		if (r_loadfog && skinframe->hasalpha)
3326 			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);
3327 		//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]);
3328 	}
3329 	else
3330 	{
3331 		basepixels_width = image_width;
3332 		basepixels_height = image_height;
3333 		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);
3334 		if (textureflags & TEXF_ALPHA)
3335 		{
3336 			for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3337 			{
3338 				if (basepixels[j] < 255)
3339 				{
3340 					skinframe->hasalpha = true;
3341 					break;
3342 				}
3343 			}
3344 			if (r_loadfog && skinframe->hasalpha)
3345 			{
3346 				// has transparent pixels
3347 				pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3348 				for (j = 0;j < image_width * image_height * 4;j += 4)
3349 				{
3350 					pixels[j+0] = 255;
3351 					pixels[j+1] = 255;
3352 					pixels[j+2] = 255;
3353 					pixels[j+3] = basepixels[j+3];
3354 				}
3355 				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);
3356 				Mem_Free(pixels);
3357 			}
3358 		}
3359 		R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3360 #ifndef USE_GLES2
3361 		//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]);
3362 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3363 			R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3364 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3365 			R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3366 #endif
3367 	}
3368 
3369 	if (r_loaddds)
3370 	{
3371 		mymiplevel = savemiplevel;
3372 		if (r_loadnormalmap)
3373 			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);
3374 		skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3375 		if (r_loadgloss)
3376 			skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3377 		skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378 		skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3379 		skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3380 	}
3381 
3382 	// _norm is the name used by tenebrae and has been adopted as standard
3383 	if (r_loadnormalmap && skinframe->nmap == NULL)
3384 	{
3385 		mymiplevel = savemiplevel;
3386 		if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3387 		{
3388 			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);
3389 			Mem_Free(pixels);
3390 			pixels = NULL;
3391 		}
3392 		else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3393 		{
3394 			pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3395 			Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3396 			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);
3397 			Mem_Free(pixels);
3398 			Mem_Free(bumppixels);
3399 		}
3400 		else if (r_shadow_bumpscale_basetexture.value > 0)
3401 		{
3402 			pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3403 			Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3404 			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);
3405 			Mem_Free(pixels);
3406 		}
3407 #ifndef USE_GLES2
3408 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3409 			R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410 #endif
3411 	}
3412 
3413 	// _luma is supported only for tenebrae compatibility
3414 	// _glow is the preferred name
3415 	mymiplevel = savemiplevel;
3416 	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))))
3417 	{
3418 		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);
3419 #ifndef USE_GLES2
3420 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3421 			R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3422 #endif
3423 		Mem_Free(pixels);pixels = NULL;
3424 	}
3425 
3426 	mymiplevel = savemiplevel;
3427 	if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3428 	{
3429 		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);
3430 #ifndef USE_GLES2
3431 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3432 			R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434 		Mem_Free(pixels);
3435 		pixels = NULL;
3436 	}
3437 
3438 	mymiplevel = savemiplevel;
3439 	if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3440 	{
3441 		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);
3442 #ifndef USE_GLES2
3443 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3444 			R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3445 #endif
3446 		Mem_Free(pixels);
3447 		pixels = NULL;
3448 	}
3449 
3450 	mymiplevel = savemiplevel;
3451 	if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3452 	{
3453 		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);
3454 #ifndef USE_GLES2
3455 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3456 			R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3457 #endif
3458 		Mem_Free(pixels);
3459 		pixels = NULL;
3460 	}
3461 
3462 	mymiplevel = savemiplevel;
3463 	if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3464 	{
3465 		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);
3466 #ifndef USE_GLES2
3467 		if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3468 			R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3469 #endif
3470 		Mem_Free(pixels);
3471 		pixels = NULL;
3472 	}
3473 
3474 	if (basepixels)
3475 		Mem_Free(basepixels);
3476 
3477 	return skinframe;
3478 }
3479 
3480 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
R_SkinFrame_LoadInternalBGRA(const char * name,int textureflags,const unsigned char * skindata,int width,int height,qboolean sRGB)3481 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3482 {
3483 	int i;
3484 	skinframe_t *skinframe;
3485 	char vabuf[1024];
3486 
3487 	if (cls.state == ca_dedicated)
3488 		return NULL;
3489 
3490 	// if already loaded just return it, otherwise make a new skinframe
3491 	skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3492 	if (skinframe->base)
3493 		return skinframe;
3494 	textureflags &= ~TEXF_FORCE_RELOAD;
3495 
3496 	skinframe->stain = NULL;
3497 	skinframe->merged = NULL;
3498 	skinframe->base = NULL;
3499 	skinframe->pants = NULL;
3500 	skinframe->shirt = NULL;
3501 	skinframe->nmap = NULL;
3502 	skinframe->gloss = NULL;
3503 	skinframe->glow = NULL;
3504 	skinframe->fog = NULL;
3505 	skinframe->reflect = NULL;
3506 	skinframe->hasalpha = false;
3507 
3508 	// if no data was provided, then clearly the caller wanted to get a blank skinframe
3509 	if (!skindata)
3510 		return NULL;
3511 
3512 	if (developer_loading.integer)
3513 		Con_Printf("loading 32bit skin \"%s\"\n", name);
3514 
3515 	if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3516 	{
3517 		unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518 		unsigned char *b = a + width * height * 4;
3519 		Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3520 		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);
3521 		Mem_Free(a);
3522 	}
3523 	skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3524 	if (textureflags & TEXF_ALPHA)
3525 	{
3526 		for (i = 3;i < width * height * 4;i += 4)
3527 		{
3528 			if (skindata[i] < 255)
3529 			{
3530 				skinframe->hasalpha = true;
3531 				break;
3532 			}
3533 		}
3534 		if (r_loadfog && skinframe->hasalpha)
3535 		{
3536 			unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3537 			memcpy(fogpixels, skindata, width * height * 4);
3538 			for (i = 0;i < width * height * 4;i += 4)
3539 				fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3540 			skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3541 			Mem_Free(fogpixels);
3542 		}
3543 	}
3544 
3545 	R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3546 	//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]);
3547 
3548 	return skinframe;
3549 }
3550 
R_SkinFrame_LoadInternalQuake(const char * name,int textureflags,int loadpantsandshirt,int loadglowtexture,const unsigned char * skindata,int width,int height)3551 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3552 {
3553 	int i;
3554 	int featuresmask;
3555 	skinframe_t *skinframe;
3556 
3557 	if (cls.state == ca_dedicated)
3558 		return NULL;
3559 
3560 	// if already loaded just return it, otherwise make a new skinframe
3561 	skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562 	if (skinframe->base)
3563 		return skinframe;
3564 	//textureflags &= ~TEXF_FORCE_RELOAD;
3565 
3566 	skinframe->stain = NULL;
3567 	skinframe->merged = NULL;
3568 	skinframe->base = NULL;
3569 	skinframe->pants = NULL;
3570 	skinframe->shirt = NULL;
3571 	skinframe->nmap = NULL;
3572 	skinframe->gloss = NULL;
3573 	skinframe->glow = NULL;
3574 	skinframe->fog = NULL;
3575 	skinframe->reflect = NULL;
3576 	skinframe->hasalpha = false;
3577 
3578 	// if no data was provided, then clearly the caller wanted to get a blank skinframe
3579 	if (!skindata)
3580 		return NULL;
3581 
3582 	if (developer_loading.integer)
3583 		Con_Printf("loading quake skin \"%s\"\n", name);
3584 
3585 	// 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)
3586 	skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3587 	memcpy(skinframe->qpixels, skindata, width*height);
3588 	skinframe->qwidth = width;
3589 	skinframe->qheight = height;
3590 
3591 	featuresmask = 0;
3592 	for (i = 0;i < width * height;i++)
3593 		featuresmask |= palette_featureflags[skindata[i]];
3594 
3595 	skinframe->hasalpha = false;
3596 	// fence textures
3597 	if (name[0] == '{')
3598 		skinframe->hasalpha = true;
3599 	skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3600 	skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3601 	skinframe->qgeneratemerged = true;
3602 	skinframe->qgeneratebase = skinframe->qhascolormapping;
3603 	skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3604 
3605 	R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3606 	//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]);
3607 
3608 	return skinframe;
3609 }
3610 
R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t * skinframe,qboolean colormapped)3611 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3612 {
3613 	int width;
3614 	int height;
3615 	unsigned char *skindata;
3616 	char vabuf[1024];
3617 
3618 	if (!skinframe->qpixels)
3619 		return;
3620 
3621 	if (!skinframe->qhascolormapping)
3622 		colormapped = false;
3623 
3624 	if (colormapped)
3625 	{
3626 		if (!skinframe->qgeneratebase)
3627 			return;
3628 	}
3629 	else
3630 	{
3631 		if (!skinframe->qgeneratemerged)
3632 			return;
3633 	}
3634 
3635 	width = skinframe->qwidth;
3636 	height = skinframe->qheight;
3637 	skindata = skinframe->qpixels;
3638 
3639 	if (skinframe->qgeneratenmap)
3640 	{
3641 		unsigned char *a, *b;
3642 		skinframe->qgeneratenmap = false;
3643 		a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3644 		b = a + width * height * 4;
3645 		// use either a custom palette or the quake palette
3646 		Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3647 		Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3648 		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);
3649 		Mem_Free(a);
3650 	}
3651 
3652 	if (skinframe->qgenerateglow)
3653 	{
3654 		skinframe->qgenerateglow = false;
3655 		if (skinframe->hasalpha) // fence textures
3656 			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
3657 		else
3658 			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
3659 	}
3660 
3661 	if (colormapped)
3662 	{
3663 		skinframe->qgeneratebase = false;
3664 		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);
3665 		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);
3666 		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);
3667 	}
3668 	else
3669 	{
3670 		skinframe->qgeneratemerged = false;
3671 		if (skinframe->hasalpha) // fence textures
3672 			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);
3673 		else
3674 			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);
3675 	}
3676 
3677 	if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3678 	{
3679 		Mem_Free(skinframe->qpixels);
3680 		skinframe->qpixels = NULL;
3681 	}
3682 }
3683 
R_SkinFrame_LoadInternal8bit(const char * name,int textureflags,const unsigned char * skindata,int width,int height,const unsigned int * palette,const unsigned int * alphapalette)3684 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)
3685 {
3686 	int i;
3687 	skinframe_t *skinframe;
3688 	char vabuf[1024];
3689 
3690 	if (cls.state == ca_dedicated)
3691 		return NULL;
3692 
3693 	// if already loaded just return it, otherwise make a new skinframe
3694 	skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3695 	if (skinframe->base)
3696 		return skinframe;
3697 	textureflags &= ~TEXF_FORCE_RELOAD;
3698 
3699 	skinframe->stain = NULL;
3700 	skinframe->merged = NULL;
3701 	skinframe->base = NULL;
3702 	skinframe->pants = NULL;
3703 	skinframe->shirt = NULL;
3704 	skinframe->nmap = NULL;
3705 	skinframe->gloss = NULL;
3706 	skinframe->glow = NULL;
3707 	skinframe->fog = NULL;
3708 	skinframe->reflect = NULL;
3709 	skinframe->hasalpha = false;
3710 
3711 	// if no data was provided, then clearly the caller wanted to get a blank skinframe
3712 	if (!skindata)
3713 		return NULL;
3714 
3715 	if (developer_loading.integer)
3716 		Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3717 
3718 	skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3719 	if ((textureflags & TEXF_ALPHA) && alphapalette)
3720 	{
3721 		for (i = 0;i < width * height;i++)
3722 		{
3723 			if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3724 			{
3725 				skinframe->hasalpha = true;
3726 				break;
3727 			}
3728 		}
3729 		if (r_loadfog && skinframe->hasalpha)
3730 			skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3731 	}
3732 
3733 	R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3734 	//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]);
3735 
3736 	return skinframe;
3737 }
3738 
R_SkinFrame_LoadMissing(void)3739 skinframe_t *R_SkinFrame_LoadMissing(void)
3740 {
3741 	skinframe_t *skinframe;
3742 
3743 	if (cls.state == ca_dedicated)
3744 		return NULL;
3745 
3746 	skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3747 	skinframe->stain = NULL;
3748 	skinframe->merged = NULL;
3749 	skinframe->base = NULL;
3750 	skinframe->pants = NULL;
3751 	skinframe->shirt = NULL;
3752 	skinframe->nmap = NULL;
3753 	skinframe->gloss = NULL;
3754 	skinframe->glow = NULL;
3755 	skinframe->fog = NULL;
3756 	skinframe->reflect = NULL;
3757 	skinframe->hasalpha = false;
3758 
3759 	skinframe->avgcolor[0] = rand() / RAND_MAX;
3760 	skinframe->avgcolor[1] = rand() / RAND_MAX;
3761 	skinframe->avgcolor[2] = rand() / RAND_MAX;
3762 	skinframe->avgcolor[3] = 1;
3763 
3764 	return skinframe;
3765 }
3766 
R_SkinFrame_LoadNoTexture(void)3767 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3768 {
3769 	int x, y;
3770 	static unsigned char pix[16][16][4];
3771 
3772 	if (cls.state == ca_dedicated)
3773 		return NULL;
3774 
3775 	// this makes a light grey/dark grey checkerboard texture
3776 	if (!pix[0][0][3])
3777 	{
3778 		for (y = 0; y < 16; y++)
3779 		{
3780 			for (x = 0; x < 16; x++)
3781 			{
3782 				if ((y < 8) ^ (x < 8))
3783 				{
3784 					pix[y][x][0] = 128;
3785 					pix[y][x][1] = 128;
3786 					pix[y][x][2] = 128;
3787 					pix[y][x][3] = 255;
3788 				}
3789 				else
3790 				{
3791 					pix[y][x][0] = 64;
3792 					pix[y][x][1] = 64;
3793 					pix[y][x][2] = 64;
3794 					pix[y][x][3] = 255;
3795 				}
3796 			}
3797 		}
3798 	}
3799 
3800 	return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3801 }
3802 
R_SkinFrame_LoadInternalUsingTexture(const char * name,int textureflags,rtexture_t * tex,int width,int height,qboolean sRGB)3803 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3804 {
3805 	skinframe_t *skinframe;
3806 	if (cls.state == ca_dedicated)
3807 		return NULL;
3808 	// if already loaded just return it, otherwise make a new skinframe
3809 	skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3810 	if (skinframe->base)
3811 		return skinframe;
3812 	textureflags &= ~TEXF_FORCE_RELOAD;
3813 	skinframe->stain = NULL;
3814 	skinframe->merged = NULL;
3815 	skinframe->base = NULL;
3816 	skinframe->pants = NULL;
3817 	skinframe->shirt = NULL;
3818 	skinframe->nmap = NULL;
3819 	skinframe->gloss = NULL;
3820 	skinframe->glow = NULL;
3821 	skinframe->fog = NULL;
3822 	skinframe->reflect = NULL;
3823 	skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3824 	// if no data was provided, then clearly the caller wanted to get a blank skinframe
3825 	if (!tex)
3826 		return NULL;
3827 	if (developer_loading.integer)
3828 		Con_Printf("loading 32bit skin \"%s\"\n", name);
3829 	skinframe->base = skinframe->merged = tex;
3830 	Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3831 	return skinframe;
3832 }
3833 
3834 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3835 typedef struct suffixinfo_s
3836 {
3837 	const char *suffix;
3838 	qboolean flipx, flipy, flipdiagonal;
3839 }
3840 suffixinfo_t;
3841 static suffixinfo_t suffix[3][6] =
3842 {
3843 	{
3844 		{"px",   false, false, false},
3845 		{"nx",   false, false, false},
3846 		{"py",   false, false, false},
3847 		{"ny",   false, false, false},
3848 		{"pz",   false, false, false},
3849 		{"nz",   false, false, false}
3850 	},
3851 	{
3852 		{"posx", false, false, false},
3853 		{"negx", false, false, false},
3854 		{"posy", false, false, false},
3855 		{"negy", false, false, false},
3856 		{"posz", false, false, false},
3857 		{"negz", false, false, false}
3858 	},
3859 	{
3860 		{"rt",    true, false,  true},
3861 		{"lf",   false,  true,  true},
3862 		{"ft",    true,  true, false},
3863 		{"bk",   false, false, false},
3864 		{"up",    true, false,  true},
3865 		{"dn",    true, false,  true}
3866 	}
3867 };
3868 
3869 static int componentorder[4] = {0, 1, 2, 3};
3870 
R_LoadCubemap(const char * basename)3871 static rtexture_t *R_LoadCubemap(const char *basename)
3872 {
3873 	int i, j, cubemapsize;
3874 	unsigned char *cubemappixels, *image_buffer;
3875 	rtexture_t *cubemaptexture;
3876 	char name[256];
3877 	// must start 0 so the first loadimagepixels has no requested width/height
3878 	cubemapsize = 0;
3879 	cubemappixels = NULL;
3880 	cubemaptexture = NULL;
3881 	// keep trying different suffix groups (posx, px, rt) until one loads
3882 	for (j = 0;j < 3 && !cubemappixels;j++)
3883 	{
3884 		// load the 6 images in the suffix group
3885 		for (i = 0;i < 6;i++)
3886 		{
3887 			// generate an image name based on the base and and suffix
3888 			dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3889 			// load it
3890 			if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3891 			{
3892 				// an image loaded, make sure width and height are equal
3893 				if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3894 				{
3895 					// if this is the first image to load successfully, allocate the cubemap memory
3896 					if (!cubemappixels && image_width >= 1)
3897 					{
3898 						cubemapsize = image_width;
3899 						// note this clears to black, so unavailable sides are black
3900 						cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3901 					}
3902 					// copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3903 					if (cubemappixels)
3904 						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);
3905 				}
3906 				else
3907 					Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3908 				// free the image
3909 				Mem_Free(image_buffer);
3910 			}
3911 		}
3912 	}
3913 	// if a cubemap loaded, upload it
3914 	if (cubemappixels)
3915 	{
3916 		if (developer_loading.integer)
3917 			Con_Printf("loading cubemap \"%s\"\n", basename);
3918 
3919 		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);
3920 		Mem_Free(cubemappixels);
3921 	}
3922 	else
3923 	{
3924 		Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3925 		if (developer_loading.integer)
3926 		{
3927 			Con_Printf("(tried tried images ");
3928 			for (j = 0;j < 3;j++)
3929 				for (i = 0;i < 6;i++)
3930 					Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3931 			Con_Print(" and was unable to find any of them).\n");
3932 		}
3933 	}
3934 	return cubemaptexture;
3935 }
3936 
R_GetCubemap(const char * basename)3937 rtexture_t *R_GetCubemap(const char *basename)
3938 {
3939 	int i;
3940 	for (i = 0;i < r_texture_numcubemaps;i++)
3941 		if (r_texture_cubemaps[i] != NULL)
3942 			if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3943 				return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3944 	if (i >= MAX_CUBEMAPS || !r_main_mempool)
3945 		return r_texture_whitecube;
3946 	r_texture_numcubemaps++;
3947 	r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3948 	strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3949 	r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3950 	return r_texture_cubemaps[i]->texture;
3951 }
3952 
R_Main_FreeViewCache(void)3953 static void R_Main_FreeViewCache(void)
3954 {
3955 	if (r_refdef.viewcache.entityvisible)
3956 		Mem_Free(r_refdef.viewcache.entityvisible);
3957 	if (r_refdef.viewcache.world_pvsbits)
3958 		Mem_Free(r_refdef.viewcache.world_pvsbits);
3959 	if (r_refdef.viewcache.world_leafvisible)
3960 		Mem_Free(r_refdef.viewcache.world_leafvisible);
3961 	if (r_refdef.viewcache.world_surfacevisible)
3962 		Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963 	memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3964 }
3965 
R_Main_ResizeViewCache(void)3966 static void R_Main_ResizeViewCache(void)
3967 {
3968 	int numentities = r_refdef.scene.numentities;
3969 	int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3970 	int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3971 	int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3972 	int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3973 	if (r_refdef.viewcache.maxentities < numentities)
3974 	{
3975 		r_refdef.viewcache.maxentities = numentities;
3976 		if (r_refdef.viewcache.entityvisible)
3977 			Mem_Free(r_refdef.viewcache.entityvisible);
3978 		r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3979 	}
3980 	if (r_refdef.viewcache.world_numclusters != numclusters)
3981 	{
3982 		r_refdef.viewcache.world_numclusters = numclusters;
3983 		r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3984 		if (r_refdef.viewcache.world_pvsbits)
3985 			Mem_Free(r_refdef.viewcache.world_pvsbits);
3986 		r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3987 	}
3988 	if (r_refdef.viewcache.world_numleafs != numleafs)
3989 	{
3990 		r_refdef.viewcache.world_numleafs = numleafs;
3991 		if (r_refdef.viewcache.world_leafvisible)
3992 			Mem_Free(r_refdef.viewcache.world_leafvisible);
3993 		r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3994 	}
3995 	if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3996 	{
3997 		r_refdef.viewcache.world_numsurfaces = numsurfaces;
3998 		if (r_refdef.viewcache.world_surfacevisible)
3999 			Mem_Free(r_refdef.viewcache.world_surfacevisible);
4000 		r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4001 	}
4002 }
4003 
4004 extern rtexture_t *loadingscreentexture;
gl_main_start(void)4005 static void gl_main_start(void)
4006 {
4007 	loadingscreentexture = NULL;
4008 	r_texture_blanknormalmap = NULL;
4009 	r_texture_white = NULL;
4010 	r_texture_grey128 = NULL;
4011 	r_texture_black = NULL;
4012 	r_texture_whitecube = NULL;
4013 	r_texture_normalizationcube = NULL;
4014 	r_texture_fogattenuation = NULL;
4015 	r_texture_fogheighttexture = NULL;
4016 	r_texture_gammaramps = NULL;
4017 	r_texture_numcubemaps = 0;
4018 	r_uniformbufferalignment = 32;
4019 
4020 	r_loaddds = r_texture_dds_load.integer != 0;
4021 	r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4022 
4023 	switch(vid.renderpath)
4024 	{
4025 	case RENDERPATH_GL20:
4026 	case RENDERPATH_D3D9:
4027 	case RENDERPATH_D3D10:
4028 	case RENDERPATH_D3D11:
4029 	case RENDERPATH_SOFT:
4030 	case RENDERPATH_GLES2:
4031 		Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032 		Cvar_SetValueQuick(&gl_combine, 1);
4033 		Cvar_SetValueQuick(&r_glsl, 1);
4034 		r_loadnormalmap = true;
4035 		r_loadgloss = true;
4036 		r_loadfog = false;
4037 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4038 		if (vid.support.arb_uniform_buffer_object)
4039 			qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4040 #endif
4041 			break;
4042 	case RENDERPATH_GL13:
4043 	case RENDERPATH_GLES1:
4044 		Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045 		Cvar_SetValueQuick(&gl_combine, 1);
4046 		Cvar_SetValueQuick(&r_glsl, 0);
4047 		r_loadnormalmap = false;
4048 		r_loadgloss = false;
4049 		r_loadfog = true;
4050 		break;
4051 	case RENDERPATH_GL11:
4052 		Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053 		Cvar_SetValueQuick(&gl_combine, 0);
4054 		Cvar_SetValueQuick(&r_glsl, 0);
4055 		r_loadnormalmap = false;
4056 		r_loadgloss = false;
4057 		r_loadfog = true;
4058 		break;
4059 	}
4060 
4061 	R_AnimCache_Free();
4062 	R_FrameData_Reset();
4063 	R_BufferData_Reset();
4064 
4065 	r_numqueries = 0;
4066 	r_maxqueries = 0;
4067 	memset(r_queries, 0, sizeof(r_queries));
4068 
4069 	r_qwskincache = NULL;
4070 	r_qwskincache_size = 0;
4071 
4072 	// due to caching of texture_t references, the collision cache must be reset
4073 	Collision_Cache_Reset(true);
4074 
4075 	// set up r_skinframe loading system for textures
4076 	memset(&r_skinframe, 0, sizeof(r_skinframe));
4077 	r_skinframe.loadsequence = 1;
4078 	Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4079 
4080 	r_main_texturepool = R_AllocTexturePool();
4081 	R_BuildBlankTextures();
4082 	R_BuildNoTexture();
4083 	if (vid.support.arb_texture_cube_map)
4084 	{
4085 		R_BuildWhiteCube();
4086 		R_BuildNormalizationCube();
4087 	}
4088 	r_texture_fogattenuation = NULL;
4089 	r_texture_fogheighttexture = NULL;
4090 	r_texture_gammaramps = NULL;
4091 	//r_texture_fogintensity = NULL;
4092 	memset(&r_fb, 0, sizeof(r_fb));
4093 	r_glsl_permutation = NULL;
4094 	memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095 	Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4096 #ifdef SUPPORTD3D
4097 	r_hlsl_permutation = NULL;
4098 	memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4099 	Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4100 #endif
4101 	memset(&r_svbsp, 0, sizeof (r_svbsp));
4102 
4103 	memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4104 	r_texture_numcubemaps = 0;
4105 
4106 	r_refdef.fogmasktable_density = 0;
4107 
4108 #ifdef __ANDROID__
4109 	// For Steelstorm Android
4110 	// FIXME CACHE the program and reload
4111 	// FIXME see possible combinations for SS:BR android
4112 	Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4113 	R_SetupShader_SetPermutationGLSL(0, 12);
4114 	R_SetupShader_SetPermutationGLSL(0, 13);
4115 	R_SetupShader_SetPermutationGLSL(0, 8388621);
4116 	R_SetupShader_SetPermutationGLSL(3, 0);
4117 	R_SetupShader_SetPermutationGLSL(3, 2048);
4118 	R_SetupShader_SetPermutationGLSL(5, 0);
4119 	R_SetupShader_SetPermutationGLSL(5, 2);
4120 	R_SetupShader_SetPermutationGLSL(5, 2048);
4121 	R_SetupShader_SetPermutationGLSL(5, 8388608);
4122 	R_SetupShader_SetPermutationGLSL(11, 1);
4123 	R_SetupShader_SetPermutationGLSL(11, 2049);
4124 	R_SetupShader_SetPermutationGLSL(11, 8193);
4125 	R_SetupShader_SetPermutationGLSL(11, 10241);
4126 	Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4127 #endif
4128 }
4129 
gl_main_shutdown(void)4130 static void gl_main_shutdown(void)
4131 {
4132 	R_AnimCache_Free();
4133 	R_FrameData_Reset();
4134 	R_BufferData_Reset();
4135 
4136 	R_Main_FreeViewCache();
4137 
4138 	switch(vid.renderpath)
4139 	{
4140 	case RENDERPATH_GL11:
4141 	case RENDERPATH_GL13:
4142 	case RENDERPATH_GL20:
4143 	case RENDERPATH_GLES1:
4144 	case RENDERPATH_GLES2:
4145 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4146 		if (r_maxqueries)
4147 			qglDeleteQueriesARB(r_maxqueries, r_queries);
4148 #endif
4149 		break;
4150 	case RENDERPATH_D3D9:
4151 		//Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4152 		break;
4153 	case RENDERPATH_D3D10:
4154 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4155 		break;
4156 	case RENDERPATH_D3D11:
4157 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4158 		break;
4159 	case RENDERPATH_SOFT:
4160 		break;
4161 	}
4162 
4163 	r_numqueries = 0;
4164 	r_maxqueries = 0;
4165 	memset(r_queries, 0, sizeof(r_queries));
4166 
4167 	r_qwskincache = NULL;
4168 	r_qwskincache_size = 0;
4169 
4170 	// clear out the r_skinframe state
4171 	Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4172 	memset(&r_skinframe, 0, sizeof(r_skinframe));
4173 
4174 	if (r_svbsp.nodes)
4175 		Mem_Free(r_svbsp.nodes);
4176 	memset(&r_svbsp, 0, sizeof (r_svbsp));
4177 	R_FreeTexturePool(&r_main_texturepool);
4178 	loadingscreentexture = NULL;
4179 	r_texture_blanknormalmap = NULL;
4180 	r_texture_white = NULL;
4181 	r_texture_grey128 = NULL;
4182 	r_texture_black = NULL;
4183 	r_texture_whitecube = NULL;
4184 	r_texture_normalizationcube = NULL;
4185 	r_texture_fogattenuation = NULL;
4186 	r_texture_fogheighttexture = NULL;
4187 	r_texture_gammaramps = NULL;
4188 	r_texture_numcubemaps = 0;
4189 	//r_texture_fogintensity = NULL;
4190 	memset(&r_fb, 0, sizeof(r_fb));
4191 	R_GLSL_Restart_f();
4192 
4193 	r_glsl_permutation = NULL;
4194 	memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4195 	Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4196 #ifdef SUPPORTD3D
4197 	r_hlsl_permutation = NULL;
4198 	memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4199 	Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4200 #endif
4201 }
4202 
gl_main_newmap(void)4203 static void gl_main_newmap(void)
4204 {
4205 	// FIXME: move this code to client
4206 	char *entities, entname[MAX_QPATH];
4207 	if (r_qwskincache)
4208 		Mem_Free(r_qwskincache);
4209 	r_qwskincache = NULL;
4210 	r_qwskincache_size = 0;
4211 	if (cl.worldmodel)
4212 	{
4213 		dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4214 		if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4215 		{
4216 			CL_ParseEntityLump(entities);
4217 			Mem_Free(entities);
4218 			return;
4219 		}
4220 		if (cl.worldmodel->brush.entities)
4221 			CL_ParseEntityLump(cl.worldmodel->brush.entities);
4222 	}
4223 	R_Main_FreeViewCache();
4224 
4225 	R_FrameData_Reset();
4226 	R_BufferData_Reset();
4227 }
4228 
GL_Main_Init(void)4229 void GL_Main_Init(void)
4230 {
4231 	int i;
4232 	r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4233 	R_InitShaderModeInfo();
4234 
4235 	Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4236 	Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4237 	// FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4238 	if (gamemode == GAME_NEHAHRA)
4239 	{
4240 		Cvar_RegisterVariable (&gl_fogenable);
4241 		Cvar_RegisterVariable (&gl_fogdensity);
4242 		Cvar_RegisterVariable (&gl_fogred);
4243 		Cvar_RegisterVariable (&gl_foggreen);
4244 		Cvar_RegisterVariable (&gl_fogblue);
4245 		Cvar_RegisterVariable (&gl_fogstart);
4246 		Cvar_RegisterVariable (&gl_fogend);
4247 		Cvar_RegisterVariable (&gl_skyclip);
4248 	}
4249 	Cvar_RegisterVariable(&r_motionblur);
4250 	Cvar_RegisterVariable(&r_damageblur);
4251 	Cvar_RegisterVariable(&r_motionblur_averaging);
4252 	Cvar_RegisterVariable(&r_motionblur_randomize);
4253 	Cvar_RegisterVariable(&r_motionblur_minblur);
4254 	Cvar_RegisterVariable(&r_motionblur_maxblur);
4255 	Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4256 	Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4257 	Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4258 	Cvar_RegisterVariable(&r_motionblur_mousefactor);
4259 	Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4260 	Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4261 	Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4262 	Cvar_RegisterVariable(&r_equalize_entities_minambient);
4263 	Cvar_RegisterVariable(&r_equalize_entities_by);
4264 	Cvar_RegisterVariable(&r_equalize_entities_to);
4265 	Cvar_RegisterVariable(&r_depthfirst);
4266 	Cvar_RegisterVariable(&r_useinfinitefarclip);
4267 	Cvar_RegisterVariable(&r_farclip_base);
4268 	Cvar_RegisterVariable(&r_farclip_world);
4269 	Cvar_RegisterVariable(&r_nearclip);
4270 	Cvar_RegisterVariable(&r_deformvertexes);
4271 	Cvar_RegisterVariable(&r_transparent);
4272 	Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4273 	Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4274 	Cvar_RegisterVariable(&r_transparent_useplanardistance);
4275 	Cvar_RegisterVariable(&r_showoverdraw);
4276 	Cvar_RegisterVariable(&r_showbboxes);
4277 	Cvar_RegisterVariable(&r_showbboxes_client);
4278 	Cvar_RegisterVariable(&r_showsurfaces);
4279 	Cvar_RegisterVariable(&r_showtris);
4280 	Cvar_RegisterVariable(&r_shownormals);
4281 	Cvar_RegisterVariable(&r_showlighting);
4282 	Cvar_RegisterVariable(&r_showshadowvolumes);
4283 	Cvar_RegisterVariable(&r_showcollisionbrushes);
4284 	Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4285 	Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4286 	Cvar_RegisterVariable(&r_showdisabledepthtest);
4287 	Cvar_RegisterVariable(&r_drawportals);
4288 	Cvar_RegisterVariable(&r_drawentities);
4289 	Cvar_RegisterVariable(&r_draw2d);
4290 	Cvar_RegisterVariable(&r_drawworld);
4291 	Cvar_RegisterVariable(&r_cullentities_trace);
4292 	Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4293 	Cvar_RegisterVariable(&r_cullentities_trace_samples);
4294 	Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4295 	Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4296 	Cvar_RegisterVariable(&r_cullentities_trace_delay);
4297 	Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4298 	Cvar_RegisterVariable(&r_sortentities);
4299 	Cvar_RegisterVariable(&r_drawviewmodel);
4300 	Cvar_RegisterVariable(&r_drawexteriormodel);
4301 	Cvar_RegisterVariable(&r_speeds);
4302 	Cvar_RegisterVariable(&r_fullbrights);
4303 	Cvar_RegisterVariable(&r_wateralpha);
4304 	Cvar_RegisterVariable(&r_dynamic);
4305 	Cvar_RegisterVariable(&r_fakelight);
4306 	Cvar_RegisterVariable(&r_fakelight_intensity);
4307 	Cvar_RegisterVariable(&r_fullbright_directed);
4308 	Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4309 	Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4310 	Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4311 	Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4312 	Cvar_RegisterVariable(&r_fullbright);
4313 	Cvar_RegisterVariable(&r_shadows);
4314 	Cvar_RegisterVariable(&r_shadows_darken);
4315 	Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316 	Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317 	Cvar_RegisterVariable(&r_shadows_throwdistance);
4318 	Cvar_RegisterVariable(&r_shadows_throwdirection);
4319 	Cvar_RegisterVariable(&r_shadows_focus);
4320 	Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321 	Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322 	Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323 	Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324 	Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325 	Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326 	Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327 	Cvar_RegisterVariable(&r_fog_exp2);
4328 	Cvar_RegisterVariable(&r_fog_clear);
4329 	Cvar_RegisterVariable(&r_drawfog);
4330 	Cvar_RegisterVariable(&r_transparentdepthmasking);
4331 	Cvar_RegisterVariable(&r_transparent_sortmindist);
4332 	Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333 	Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334 	Cvar_RegisterVariable(&r_texture_dds_load);
4335 	Cvar_RegisterVariable(&r_texture_dds_save);
4336 	Cvar_RegisterVariable(&r_textureunits);
4337 	Cvar_RegisterVariable(&gl_combine);
4338 	Cvar_RegisterVariable(&r_usedepthtextures);
4339 	Cvar_RegisterVariable(&r_viewfbo);
4340 	Cvar_RegisterVariable(&r_viewscale);
4341 	Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342 	Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343 	Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344 	Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345 	Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346 	Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347 	Cvar_RegisterVariable(&r_glsl);
4348 	Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349 	Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350 	Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351 	Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352 	Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353 	Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354 	Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355 	Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356 	Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357 	Cvar_RegisterVariable(&r_glsl_postprocess);
4358 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365 	Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366 	Cvar_RegisterVariable(&r_celshading);
4367 	Cvar_RegisterVariable(&r_celoutlines);
4368 
4369 	Cvar_RegisterVariable(&r_water);
4370 	Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4371 	Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4372 	Cvar_RegisterVariable(&r_water_clippingplanebias);
4373 	Cvar_RegisterVariable(&r_water_refractdistort);
4374 	Cvar_RegisterVariable(&r_water_reflectdistort);
4375 	Cvar_RegisterVariable(&r_water_scissormode);
4376 	Cvar_RegisterVariable(&r_water_lowquality);
4377 	Cvar_RegisterVariable(&r_water_hideplayer);
4378 	Cvar_RegisterVariable(&r_water_fbo);
4379 
4380 	Cvar_RegisterVariable(&r_lerpsprites);
4381 	Cvar_RegisterVariable(&r_lerpmodels);
4382 	Cvar_RegisterVariable(&r_lerplightstyles);
4383 	Cvar_RegisterVariable(&r_waterscroll);
4384 	Cvar_RegisterVariable(&r_bloom);
4385 	Cvar_RegisterVariable(&r_bloom_colorscale);
4386 	Cvar_RegisterVariable(&r_bloom_brighten);
4387 	Cvar_RegisterVariable(&r_bloom_blur);
4388 	Cvar_RegisterVariable(&r_bloom_resolution);
4389 	Cvar_RegisterVariable(&r_bloom_colorexponent);
4390 	Cvar_RegisterVariable(&r_bloom_colorsubtract);
4391 	Cvar_RegisterVariable(&r_bloom_scenebrightness);
4392 	Cvar_RegisterVariable(&r_hdr_scenebrightness);
4393 	Cvar_RegisterVariable(&r_hdr_glowintensity);
4394 	Cvar_RegisterVariable(&r_hdr_irisadaptation);
4395 	Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4396 	Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4397 	Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4398 	Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4399 	Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4400 	Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4401 	Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4402 	Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4403 	Cvar_RegisterVariable(&developer_texturelogging);
4404 	Cvar_RegisterVariable(&gl_lightmaps);
4405 	Cvar_RegisterVariable(&r_test);
4406 	Cvar_RegisterVariable(&r_batch_multidraw);
4407 	Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4408 	Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4409 	Cvar_RegisterVariable(&r_glsl_skeletal);
4410 	Cvar_RegisterVariable(&r_glsl_saturation);
4411 	Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4412 	Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4413 	Cvar_RegisterVariable(&r_framedatasize);
4414 	for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4415 		Cvar_RegisterVariable(&r_buffermegs[i]);
4416 	Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4417 	if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4418 		Cvar_SetValue("r_fullbrights", 0);
4419 #ifdef DP_MOBILETOUCH
4420 	// GLES devices have terrible depth precision in general, so...
4421 	Cvar_SetValueQuick(&r_nearclip, 4);
4422 	Cvar_SetValueQuick(&r_farclip_base, 4096);
4423 	Cvar_SetValueQuick(&r_farclip_world, 0);
4424 	Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 #endif
4426 	R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4427 }
4428 
Render_Init(void)4429 void Render_Init(void)
4430 {
4431 	gl_backend_init();
4432 	R_Textures_Init();
4433 	GL_Main_Init();
4434 	Font_Init();
4435 	GL_Draw_Init();
4436 	R_Shadow_Init();
4437 	R_Sky_Init();
4438 	GL_Surf_Init();
4439 	Sbar_Init();
4440 	R_Particles_Init();
4441 	R_Explosion_Init();
4442 	R_LightningBeams_Init();
4443 	Mod_RenderInit();
4444 }
4445 
4446 /*
4447 ===============
4448 GL_Init
4449 ===============
4450 */
4451 #ifndef USE_GLES2
4452 extern char *ENGINE_EXTENSIONS;
GL_Init(void)4453 void GL_Init (void)
4454 {
4455 	gl_renderer = (const char *)qglGetString(GL_RENDERER);
4456 	gl_vendor = (const char *)qglGetString(GL_VENDOR);
4457 	gl_version = (const char *)qglGetString(GL_VERSION);
4458 	gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4459 
4460 	if (!gl_extensions)
4461 		gl_extensions = "";
4462 	if (!gl_platformextensions)
4463 		gl_platformextensions = "";
4464 
4465 	Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4466 	Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4467 	Con_Printf("GL_VERSION: %s\n", gl_version);
4468 	Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4469 	Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470 
4471 	VID_CheckExtensions();
4472 
4473 	// LordHavoc: report supported extensions
4474 #ifdef CONFIG_MENU
4475 	Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 #else
4477 	Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4478 #endif
4479 
4480 	// clear to black (loading plaque will be seen over this)
4481 	GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4482 }
4483 #endif
4484 
R_CullBox(const vec3_t mins,const vec3_t maxs)4485 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4486 {
4487 	int i;
4488 	mplane_t *p;
4489 	if (r_trippy.integer)
4490 		return false;
4491 	for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492 	{
4493 		p = r_refdef.view.frustum + i;
4494 		switch(p->signbits)
4495 		{
4496 		default:
4497 		case 0:
4498 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499 				return true;
4500 			break;
4501 		case 1:
4502 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503 				return true;
4504 			break;
4505 		case 2:
4506 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507 				return true;
4508 			break;
4509 		case 3:
4510 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511 				return true;
4512 			break;
4513 		case 4:
4514 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515 				return true;
4516 			break;
4517 		case 5:
4518 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519 				return true;
4520 			break;
4521 		case 6:
4522 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4523 				return true;
4524 			break;
4525 		case 7:
4526 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527 				return true;
4528 			break;
4529 		}
4530 	}
4531 	return false;
4532 }
4533 
R_CullBoxCustomPlanes(const vec3_t mins,const vec3_t maxs,int numplanes,const mplane_t * planes)4534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4535 {
4536 	int i;
4537 	const mplane_t *p;
4538 	if (r_trippy.integer)
4539 		return false;
4540 	for (i = 0;i < numplanes;i++)
4541 	{
4542 		p = planes + i;
4543 		switch(p->signbits)
4544 		{
4545 		default:
4546 		case 0:
4547 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4548 				return true;
4549 			break;
4550 		case 1:
4551 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4552 				return true;
4553 			break;
4554 		case 2:
4555 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4556 				return true;
4557 			break;
4558 		case 3:
4559 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4560 				return true;
4561 			break;
4562 		case 4:
4563 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4564 				return true;
4565 			break;
4566 		case 5:
4567 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4568 				return true;
4569 			break;
4570 		case 6:
4571 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4572 				return true;
4573 			break;
4574 		case 7:
4575 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4576 				return true;
4577 			break;
4578 		}
4579 	}
4580 	return false;
4581 }
4582 
4583 //==================================================================================
4584 
4585 // LordHavoc: this stores temporary data used within the same frame
4586 
4587 typedef struct r_framedata_mem_s
4588 {
4589 	struct r_framedata_mem_s *purge; // older mem block to free on next frame
4590 	size_t size; // how much usable space
4591 	size_t current; // how much space in use
4592 	size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4593 	size_t wantedsize; // how much space was allocated
4594 	unsigned char *data; // start of real data (16byte aligned)
4595 }
4596 r_framedata_mem_t;
4597 
4598 static r_framedata_mem_t *r_framedata_mem;
4599 
R_FrameData_Reset(void)4600 void R_FrameData_Reset(void)
4601 {
4602 	while (r_framedata_mem)
4603 	{
4604 		r_framedata_mem_t *next = r_framedata_mem->purge;
4605 		Mem_Free(r_framedata_mem);
4606 		r_framedata_mem = next;
4607 	}
4608 }
4609 
R_FrameData_Resize(qboolean mustgrow)4610 static void R_FrameData_Resize(qboolean mustgrow)
4611 {
4612 	size_t wantedsize;
4613 	wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4614 	wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4615 	if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4616 	{
4617 		r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4618 		newmem->wantedsize = wantedsize;
4619 		newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4620 		newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4621 		newmem->current = 0;
4622 		newmem->mark = 0;
4623 		newmem->purge = r_framedata_mem;
4624 		r_framedata_mem = newmem;
4625 	}
4626 }
4627 
R_FrameData_NewFrame(void)4628 void R_FrameData_NewFrame(void)
4629 {
4630 	R_FrameData_Resize(false);
4631 	if (!r_framedata_mem)
4632 		return;
4633 	// if we ran out of space on the last frame, free the old memory now
4634 	while (r_framedata_mem->purge)
4635 	{
4636 		// repeatedly remove the second item in the list, leaving only head
4637 		r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4638 		Mem_Free(r_framedata_mem->purge);
4639 		r_framedata_mem->purge = next;
4640 	}
4641 	// reset the current mem pointer
4642 	r_framedata_mem->current = 0;
4643 	r_framedata_mem->mark = 0;
4644 }
4645 
R_FrameData_Alloc(size_t size)4646 void *R_FrameData_Alloc(size_t size)
4647 {
4648 	void *data;
4649 	float newvalue;
4650 
4651 	// align to 16 byte boundary - the data pointer is already aligned, so we
4652 	// only need to ensure the size of every allocation is also aligned
4653 	size = (size + 15) & ~15;
4654 
4655 	while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4656 	{
4657 		// emergency - we ran out of space, allocate more memory
4658 		// note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4659 		newvalue = r_framedatasize.value * 2.0f;
4660 		// upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4661 		if (sizeof(size_t) >= 8)
4662 			newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4663 		else
4664 			newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4665 		// this might not be a growing it, but we'll allocate another buffer every time
4666 		Cvar_SetValueQuick(&r_framedatasize, newvalue);
4667 		R_FrameData_Resize(true);
4668 	}
4669 
4670 	data = r_framedata_mem->data + r_framedata_mem->current;
4671 	r_framedata_mem->current += size;
4672 
4673 	// count the usage for stats
4674 	r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4675 	r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4676 
4677 	return (void *)data;
4678 }
4679 
R_FrameData_Store(size_t size,void * data)4680 void *R_FrameData_Store(size_t size, void *data)
4681 {
4682 	void *d = R_FrameData_Alloc(size);
4683 	if (d && data)
4684 		memcpy(d, data, size);
4685 	return d;
4686 }
4687 
R_FrameData_SetMark(void)4688 void R_FrameData_SetMark(void)
4689 {
4690 	if (!r_framedata_mem)
4691 		return;
4692 	r_framedata_mem->mark = r_framedata_mem->current;
4693 }
4694 
R_FrameData_ReturnToMark(void)4695 void R_FrameData_ReturnToMark(void)
4696 {
4697 	if (!r_framedata_mem)
4698 		return;
4699 	r_framedata_mem->current = r_framedata_mem->mark;
4700 }
4701 
4702 //==================================================================================
4703 
4704 // avoid reusing the same buffer objects on consecutive frames
4705 #define R_BUFFERDATA_CYCLE 3
4706 
4707 typedef struct r_bufferdata_buffer_s
4708 {
4709 	struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4710 	size_t size; // how much usable space
4711 	size_t current; // how much space in use
4712 	r_meshbuffer_t *buffer; // the buffer itself
4713 }
4714 r_bufferdata_buffer_t;
4715 
4716 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4717 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4718 
4719 /// frees all dynamic buffers
R_BufferData_Reset(void)4720 void R_BufferData_Reset(void)
4721 {
4722 	int cycle, type;
4723 	r_bufferdata_buffer_t **p, *mem;
4724 	for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4725 	{
4726 		for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4727 		{
4728 			// free all buffers
4729 			p = &r_bufferdata_buffer[cycle][type];
4730 			while (*p)
4731 			{
4732 				mem = *p;
4733 				*p = (*p)->purge;
4734 				if (mem->buffer)
4735 					R_Mesh_DestroyMeshBuffer(mem->buffer);
4736 				Mem_Free(mem);
4737 			}
4738 		}
4739 	}
4740 }
4741 
4742 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
R_BufferData_Resize(r_bufferdata_type_t type,qboolean mustgrow,size_t minsize)4743 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4744 {
4745 	r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4746 	size_t size;
4747 	float newvalue = r_buffermegs[type].value;
4748 
4749 	// increase the cvar if we have to (but only if we already have a mem)
4750 	if (mustgrow && mem)
4751 		newvalue *= 2.0f;
4752 	newvalue = bound(0.25f, newvalue, 256.0f);
4753 	while (newvalue * 1024*1024 < minsize)
4754 		newvalue *= 2.0f;
4755 
4756 	// clamp the cvar to valid range
4757 	newvalue = bound(0.25f, newvalue, 256.0f);
4758 	if (r_buffermegs[type].value != newvalue)
4759 		Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4760 
4761 	// calculate size in bytes
4762 	size = (size_t)(newvalue * 1024*1024);
4763 	size = bound(131072, size, 256*1024*1024);
4764 
4765 	// allocate a new buffer if the size is different (purge old one later)
4766 	// or if we were told we must grow the buffer
4767 	if (!mem || mem->size != size || mustgrow)
4768 	{
4769 		mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4770 		mem->size = size;
4771 		mem->current = 0;
4772 		if (type == R_BUFFERDATA_VERTEX)
4773 			mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4774 		else if (type == R_BUFFERDATA_INDEX16)
4775 			mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4776 		else if (type == R_BUFFERDATA_INDEX32)
4777 			mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4778 		else if (type == R_BUFFERDATA_UNIFORM)
4779 			mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4780 		mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781 		r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4782 	}
4783 }
4784 
R_BufferData_NewFrame(void)4785 void R_BufferData_NewFrame(void)
4786 {
4787 	int type;
4788 	r_bufferdata_buffer_t **p, *mem;
4789 	// cycle to the next frame's buffers
4790 	r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4791 	// if we ran out of space on the last time we used these buffers, free the old memory now
4792 	for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4793 	{
4794 		if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4795 		{
4796 			R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4797 			// free all but the head buffer, this is how we recycle obsolete
4798 			// buffers after they are no longer in use
4799 			p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4800 			while (*p)
4801 			{
4802 				mem = *p;
4803 				*p = (*p)->purge;
4804 				if (mem->buffer)
4805 					R_Mesh_DestroyMeshBuffer(mem->buffer);
4806 				Mem_Free(mem);
4807 			}
4808 			// reset the current offset
4809 			r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810 		}
4811 	}
4812 }
4813 
R_BufferData_Store(size_t datasize,const void * data,r_bufferdata_type_t type,int * returnbufferoffset)4814 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4815 {
4816 	r_bufferdata_buffer_t *mem;
4817 	int offset = 0;
4818 	int padsize;
4819 
4820 	*returnbufferoffset = 0;
4821 
4822 	// align size to a byte boundary appropriate for the buffer type, this
4823 	// makes all allocations have aligned start offsets
4824 	if (type == R_BUFFERDATA_UNIFORM)
4825 		padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4826 	else
4827 		padsize = (datasize + 15) & ~15;
4828 
4829 	// if we ran out of space in this buffer we must allocate a new one
4830 	if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4831 		R_BufferData_Resize(type, true, padsize);
4832 
4833 	// if the resize did not give us enough memory, fail
4834 	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)
4835 		Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4836 
4837 	mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4838 	offset = (int)mem->current;
4839 	mem->current += padsize;
4840 
4841 	// upload the data to the buffer at the chosen offset
4842 	if (offset == 0)
4843 		R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4844 	R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4845 
4846 	// count the usage for stats
4847 	r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4848 	r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4849 
4850 	// return the buffer offset
4851 	*returnbufferoffset = offset;
4852 
4853 	return mem->buffer;
4854 }
4855 
4856 //==================================================================================
4857 
4858 // LordHavoc: animcache originally written by Echon, rewritten since then
4859 
4860 /**
4861  * Animation cache prevents re-generating mesh data for an animated model
4862  * multiple times in one frame for lighting, shadowing, reflections, etc.
4863  */
4864 
R_AnimCache_Free(void)4865 void R_AnimCache_Free(void)
4866 {
4867 }
4868 
R_AnimCache_ClearCache(void)4869 void R_AnimCache_ClearCache(void)
4870 {
4871 	int i;
4872 	entity_render_t *ent;
4873 
4874 	for (i = 0;i < r_refdef.scene.numentities;i++)
4875 	{
4876 		ent = r_refdef.scene.entities[i];
4877 		ent->animcache_vertex3f = NULL;
4878 		ent->animcache_vertex3f_vertexbuffer = NULL;
4879 		ent->animcache_vertex3f_bufferoffset = 0;
4880 		ent->animcache_normal3f = NULL;
4881 		ent->animcache_normal3f_vertexbuffer = NULL;
4882 		ent->animcache_normal3f_bufferoffset = 0;
4883 		ent->animcache_svector3f = NULL;
4884 		ent->animcache_svector3f_vertexbuffer = NULL;
4885 		ent->animcache_svector3f_bufferoffset = 0;
4886 		ent->animcache_tvector3f = NULL;
4887 		ent->animcache_tvector3f_vertexbuffer = NULL;
4888 		ent->animcache_tvector3f_bufferoffset = 0;
4889 		ent->animcache_vertexmesh = NULL;
4890 		ent->animcache_vertexmesh_vertexbuffer = NULL;
4891 		ent->animcache_vertexmesh_bufferoffset = 0;
4892 		ent->animcache_skeletaltransform3x4 = NULL;
4893 		ent->animcache_skeletaltransform3x4buffer = NULL;
4894 		ent->animcache_skeletaltransform3x4offset = 0;
4895 		ent->animcache_skeletaltransform3x4size = 0;
4896 	}
4897 }
4898 
R_AnimCache_UpdateEntityMeshBuffers(entity_render_t * ent,int numvertices)4899 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4900 {
4901 	int i;
4902 
4903 	// check if we need the meshbuffers
4904 	if (!vid.useinterleavedarrays)
4905 		return;
4906 
4907 	if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4908 		ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4909 	// TODO: upload vertexbuffer?
4910 	if (ent->animcache_vertexmesh)
4911 	{
4912 		r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4913 		r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4914 		r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4915 		memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4916 		for (i = 0;i < numvertices;i++)
4917 			memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4918 		if (ent->animcache_svector3f)
4919 			for (i = 0;i < numvertices;i++)
4920 				memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4921 		if (ent->animcache_tvector3f)
4922 			for (i = 0;i < numvertices;i++)
4923 				memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4924 		if (ent->animcache_normal3f)
4925 			for (i = 0;i < numvertices;i++)
4926 				memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4927 	}
4928 }
4929 
R_AnimCache_GetEntity(entity_render_t * ent,qboolean wantnormals,qboolean wanttangents)4930 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4931 {
4932 	dp_model_t *model = ent->model;
4933 	int numvertices;
4934 
4935 	// see if this ent is worth caching
4936 	if (!model || !model->Draw || !model->AnimateVertices)
4937 		return false;
4938 	// nothing to cache if it contains no animations and has no skeleton
4939 	if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4940 		return false;
4941 	// see if it is already cached for gpuskeletal
4942 	if (ent->animcache_skeletaltransform3x4)
4943 		return false;
4944 	// see if it is already cached as a mesh
4945 	if (ent->animcache_vertex3f)
4946 	{
4947 		// check if we need to add normals or tangents
4948 		if (ent->animcache_normal3f)
4949 			wantnormals = false;
4950 		if (ent->animcache_svector3f)
4951 			wanttangents = false;
4952 		if (!wantnormals && !wanttangents)
4953 			return false;
4954 	}
4955 
4956 	// check which kind of cache we need to generate
4957 	if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4958 	{
4959 		// cache the skeleton so the vertex shader can use it
4960 		r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4961 		r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4962 		r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4963 		ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4964 		Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4965 		// note: this can fail if the buffer is at the grow limit
4966 		ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4967 		ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4968 	}
4969 	else if (ent->animcache_vertex3f)
4970 	{
4971 		// mesh was already cached but we may need to add normals/tangents
4972 		// (this only happens with multiple views, reflections, cameras, etc)
4973 		if (wantnormals || wanttangents)
4974 		{
4975 			numvertices = model->surfmesh.num_vertices;
4976 			if (wantnormals)
4977 				ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978 			if (wanttangents)
4979 			{
4980 				ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981 				ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982 			}
4983 			model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4984 			R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985 			r_refdef.stats[r_stat_animcache_shade_count] += 1;
4986 			r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4987 			r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988 		}
4989 	}
4990 	else
4991 	{
4992 		// generate mesh cache
4993 		numvertices = model->surfmesh.num_vertices;
4994 		ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995 		if (wantnormals)
4996 			ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997 		if (wanttangents)
4998 		{
4999 			ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000 			ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001 		}
5002 		model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5003 		R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5004 		if (wantnormals || wanttangents)
5005 		{
5006 			r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007 			r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008 			r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5009 		}
5010 		r_refdef.stats[r_stat_animcache_shape_count] += 1;
5011 		r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5012 		r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013 	}
5014 	return true;
5015 }
5016 
R_AnimCache_CacheVisibleEntities(void)5017 void R_AnimCache_CacheVisibleEntities(void)
5018 {
5019 	int i;
5020 	qboolean wantnormals = true;
5021 	qboolean wanttangents = !r_showsurfaces.integer;
5022 
5023 	switch(vid.renderpath)
5024 	{
5025 	case RENDERPATH_GL20:
5026 	case RENDERPATH_D3D9:
5027 	case RENDERPATH_D3D10:
5028 	case RENDERPATH_D3D11:
5029 	case RENDERPATH_GLES2:
5030 		break;
5031 	case RENDERPATH_GL11:
5032 	case RENDERPATH_GL13:
5033 	case RENDERPATH_GLES1:
5034 		wanttangents = false;
5035 		break;
5036 	case RENDERPATH_SOFT:
5037 		break;
5038 	}
5039 
5040 	if (r_shownormals.integer)
5041 		wanttangents = wantnormals = true;
5042 
5043 	// TODO: thread this
5044 	// NOTE: R_PrepareRTLights() also caches entities
5045 
5046 	for (i = 0;i < r_refdef.scene.numentities;i++)
5047 		if (r_refdef.viewcache.entityvisible[i])
5048 			R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5049 }
5050 
5051 //==================================================================================
5052 
R_CanSeeBox(int numsamples,vec_t eyejitter,vec_t entboxenlarge,vec3_t eye,vec3_t entboxmins,vec3_t entboxmaxs)5053 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5054 {
5055 	int i;
5056 	vec3_t eyemins, eyemaxs;
5057 	vec3_t boxmins, boxmaxs;
5058 	vec3_t start;
5059 	vec3_t end;
5060 	dp_model_t *model = r_refdef.scene.worldmodel;
5061 	static vec3_t positions[] = {
5062 		{ 0.5f, 0.5f, 0.5f },
5063 		{ 0.0f, 0.0f, 0.0f },
5064 		{ 0.0f, 0.0f, 1.0f },
5065 		{ 0.0f, 1.0f, 0.0f },
5066 		{ 0.0f, 1.0f, 1.0f },
5067 		{ 1.0f, 0.0f, 0.0f },
5068 		{ 1.0f, 0.0f, 1.0f },
5069 		{ 1.0f, 1.0f, 0.0f },
5070 		{ 1.0f, 1.0f, 1.0f },
5071 	};
5072 
5073 	// sample count can be set to -1 to skip this logic, for flicker-prone objects
5074 	if (numsamples < 0)
5075 		return true;
5076 
5077 	// view origin is not used for culling in portal/reflection/refraction renders or isometric views
5078 	if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5079 		return true;
5080 
5081 	if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5082 		return true;
5083 
5084 	// expand the eye box a little
5085 	eyemins[0] = eye[0] - eyejitter;
5086 	eyemaxs[0] = eye[0] + eyejitter;
5087 	eyemins[1] = eye[1] - eyejitter;
5088 	eyemaxs[1] = eye[1] + eyejitter;
5089 	eyemins[2] = eye[2] - eyejitter;
5090 	eyemaxs[2] = eye[2] + eyejitter;
5091 	// expand the box a little
5092 	boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5093 	boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5094 	boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5095 	boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5096 	boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5097 	boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5098 
5099 	// return true if eye overlaps enlarged box
5100 	if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5101 		return true;
5102 
5103 	// try specific positions in the box first - note that these can be cached
5104 	if (r_cullentities_trace_entityocclusion.integer)
5105 	{
5106 		for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5107 		{
5108 			VectorCopy(eye, start);
5109 			end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5110 			end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5111 			end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5112 			//trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5113 			trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5114 			// not picky - if the trace ended anywhere in the box we're good
5115 			if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5116 				return true;
5117 		}
5118 	}
5119 	else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5120 		return true;
5121 
5122 	// try various random positions
5123 	for (i = 0; i < numsamples; i++)
5124 	{
5125 		VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5126 		VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5127 		if (r_cullentities_trace_entityocclusion.integer)
5128 		{
5129 			trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5130 			// not picky - if the trace ended anywhere in the box we're good
5131 			if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5132 				return true;
5133 		}
5134 		else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5135 			return true;
5136 	}
5137 
5138 	return false;
5139 }
5140 
5141 
R_View_UpdateEntityVisible(void)5142 static void R_View_UpdateEntityVisible (void)
5143 {
5144 	int i;
5145 	int renderimask;
5146 	int samples;
5147 	entity_render_t *ent;
5148 
5149 	if (r_refdef.envmap || r_fb.water.hideplayer)
5150 		renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5151 	else if (chase_active.integer || r_fb.water.renderingscene)
5152 		renderimask = RENDER_VIEWMODEL;
5153 	else
5154 		renderimask = RENDER_EXTERIORMODEL;
5155 	if (!r_drawviewmodel.integer)
5156 		renderimask |= RENDER_VIEWMODEL;
5157 	if (!r_drawexteriormodel.integer)
5158 		renderimask |= RENDER_EXTERIORMODEL;
5159 	memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5160 	if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5161 	{
5162 		// worldmodel can check visibility
5163 		for (i = 0;i < r_refdef.scene.numentities;i++)
5164 		{
5165 			ent = r_refdef.scene.entities[i];
5166 			if (!(ent->flags & renderimask))
5167 			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)))
5168 			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))
5169 				r_refdef.viewcache.entityvisible[i] = true;
5170 		}
5171 	}
5172 	else
5173 	{
5174 		// no worldmodel or it can't check visibility
5175 		for (i = 0;i < r_refdef.scene.numentities;i++)
5176 		{
5177 			ent = r_refdef.scene.entities[i];
5178 			if (!(ent->flags & renderimask))
5179 			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)))
5180 				r_refdef.viewcache.entityvisible[i] = true;
5181 		}
5182 	}
5183 	if (r_cullentities_trace.integer)
5184 	{
5185 		for (i = 0;i < r_refdef.scene.numentities;i++)
5186 		{
5187 			if (!r_refdef.viewcache.entityvisible[i])
5188 				continue;
5189 			ent = r_refdef.scene.entities[i];
5190 			if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5191 			{
5192 				samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5193 				if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5194 					ent->last_trace_visibility = realtime;
5195 				if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5196 					r_refdef.viewcache.entityvisible[i] = 0;
5197 			}
5198 		}
5199 	}
5200 }
5201 
5202 /// only used if skyrendermasked, and normally returns false
R_DrawBrushModelsSky(void)5203 static int R_DrawBrushModelsSky (void)
5204 {
5205 	int i, sky;
5206 	entity_render_t *ent;
5207 
5208 	sky = false;
5209 	for (i = 0;i < r_refdef.scene.numentities;i++)
5210 	{
5211 		if (!r_refdef.viewcache.entityvisible[i])
5212 			continue;
5213 		ent = r_refdef.scene.entities[i];
5214 		if (!ent->model || !ent->model->DrawSky)
5215 			continue;
5216 		ent->model->DrawSky(ent);
5217 		sky = true;
5218 	}
5219 	return sky;
5220 }
5221 
5222 static void R_DrawNoModel(entity_render_t *ent);
R_DrawModels(void)5223 static void R_DrawModels(void)
5224 {
5225 	int i;
5226 	entity_render_t *ent;
5227 
5228 	for (i = 0;i < r_refdef.scene.numentities;i++)
5229 	{
5230 		if (!r_refdef.viewcache.entityvisible[i])
5231 			continue;
5232 		ent = r_refdef.scene.entities[i];
5233 		r_refdef.stats[r_stat_entities]++;
5234 		/*
5235 		if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5236 		{
5237 			vec3_t f, l, u, o;
5238 			Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5239 			Con_Printf("R_DrawModels\n");
5240 			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]);
5241 			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);
5242 			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);
5243 		}
5244 		*/
5245 		if (ent->model && ent->model->Draw != NULL)
5246 			ent->model->Draw(ent);
5247 		else
5248 			R_DrawNoModel(ent);
5249 	}
5250 }
5251 
R_DrawModelsDepth(void)5252 static void R_DrawModelsDepth(void)
5253 {
5254 	int i;
5255 	entity_render_t *ent;
5256 
5257 	for (i = 0;i < r_refdef.scene.numentities;i++)
5258 	{
5259 		if (!r_refdef.viewcache.entityvisible[i])
5260 			continue;
5261 		ent = r_refdef.scene.entities[i];
5262 		if (ent->model && ent->model->DrawDepth != NULL)
5263 			ent->model->DrawDepth(ent);
5264 	}
5265 }
5266 
R_DrawModelsDebug(void)5267 static void R_DrawModelsDebug(void)
5268 {
5269 	int i;
5270 	entity_render_t *ent;
5271 
5272 	for (i = 0;i < r_refdef.scene.numentities;i++)
5273 	{
5274 		if (!r_refdef.viewcache.entityvisible[i])
5275 			continue;
5276 		ent = r_refdef.scene.entities[i];
5277 		if (ent->model && ent->model->DrawDebug != NULL)
5278 			ent->model->DrawDebug(ent);
5279 	}
5280 }
5281 
R_DrawModelsAddWaterPlanes(void)5282 static void R_DrawModelsAddWaterPlanes(void)
5283 {
5284 	int i;
5285 	entity_render_t *ent;
5286 
5287 	for (i = 0;i < r_refdef.scene.numentities;i++)
5288 	{
5289 		if (!r_refdef.viewcache.entityvisible[i])
5290 			continue;
5291 		ent = r_refdef.scene.entities[i];
5292 		if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5293 			ent->model->DrawAddWaterPlanes(ent);
5294 	}
5295 }
5296 
5297 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}};
5298 
R_HDR_UpdateIrisAdaptation(const vec3_t point)5299 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5300 {
5301 	if (r_hdr_irisadaptation.integer)
5302 	{
5303 		vec3_t p;
5304 		vec3_t ambient;
5305 		vec3_t diffuse;
5306 		vec3_t diffusenormal;
5307 		vec3_t forward;
5308 		vec_t brightness = 0.0f;
5309 		vec_t goal;
5310 		vec_t current;
5311 		vec_t d;
5312 		int c;
5313 		VectorCopy(r_refdef.view.forward, forward);
5314 		for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5315 		{
5316 			p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5317 			p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5318 			p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5319 			R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5320 			d = DotProduct(forward, diffusenormal);
5321 			brightness += VectorLength(ambient);
5322 			if (d > 0)
5323 				brightness += d * VectorLength(diffuse);
5324 		}
5325 		brightness *= 1.0f / c;
5326 		brightness += 0.00001f; // make sure it's never zero
5327 		goal = r_hdr_irisadaptation_multiplier.value / brightness;
5328 		goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5329 		current = r_hdr_irisadaptation_value.value;
5330 		if (current < goal)
5331 			current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5332 		else if (current > goal)
5333 			current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5334 		if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5335 			Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5336 	}
5337 	else if (r_hdr_irisadaptation_value.value != 1.0f)
5338 		Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5339 }
5340 
R_View_SetFrustum(const int * scissor)5341 static void R_View_SetFrustum(const int *scissor)
5342 {
5343 	int i;
5344 	double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5345 	vec3_t forward, left, up, origin, v;
5346 
5347 	if(scissor)
5348 	{
5349 		// flipped x coordinates (because x points left here)
5350 		fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5351 		fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5352 
5353 		// D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5354 		switch(vid.renderpath)
5355 		{
5356 			case RENDERPATH_D3D9:
5357 			case RENDERPATH_D3D10:
5358 			case RENDERPATH_D3D11:
5359 				// non-flipped y coordinates
5360 				fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361 				fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5362 				break;
5363 			case RENDERPATH_SOFT:
5364 			case RENDERPATH_GL11:
5365 			case RENDERPATH_GL13:
5366 			case RENDERPATH_GL20:
5367 			case RENDERPATH_GLES1:
5368 			case RENDERPATH_GLES2:
5369 				// non-flipped y coordinates
5370 				fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5371 				fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5372 				break;
5373 		}
5374 	}
5375 
5376 	// we can't trust r_refdef.view.forward and friends in reflected scenes
5377 	Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5378 
5379 #if 0
5380 	r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5381 	r_refdef.view.frustum[0].normal[1] = 0 - 0;
5382 	r_refdef.view.frustum[0].normal[2] = -1 - 0;
5383 	r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5384 	r_refdef.view.frustum[1].normal[1] = 0 + 0;
5385 	r_refdef.view.frustum[1].normal[2] = -1 + 0;
5386 	r_refdef.view.frustum[2].normal[0] = 0 - 0;
5387 	r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5388 	r_refdef.view.frustum[2].normal[2] = -1 - 0;
5389 	r_refdef.view.frustum[3].normal[0] = 0 + 0;
5390 	r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5391 	r_refdef.view.frustum[3].normal[2] = -1 + 0;
5392 #endif
5393 
5394 #if 0
5395 	zNear = r_refdef.nearclip;
5396 	nudge = 1.0 - 1.0 / (1<<23);
5397 	r_refdef.view.frustum[4].normal[0] = 0 - 0;
5398 	r_refdef.view.frustum[4].normal[1] = 0 - 0;
5399 	r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5400 	r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5401 	r_refdef.view.frustum[5].normal[0] = 0 + 0;
5402 	r_refdef.view.frustum[5].normal[1] = 0 + 0;
5403 	r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5404 	r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5405 #endif
5406 
5407 
5408 
5409 #if 0
5410 	r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5411 	r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5412 	r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5413 	r_refdef.view.frustum[0].dist = m[15] - m[12];
5414 
5415 	r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5416 	r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5417 	r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5418 	r_refdef.view.frustum[1].dist = m[15] + m[12];
5419 
5420 	r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5421 	r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5422 	r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5423 	r_refdef.view.frustum[2].dist = m[15] - m[13];
5424 
5425 	r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5426 	r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5427 	r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5428 	r_refdef.view.frustum[3].dist = m[15] + m[13];
5429 
5430 	r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5431 	r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5432 	r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5433 	r_refdef.view.frustum[4].dist = m[15] - m[14];
5434 
5435 	r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5436 	r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5437 	r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5438 	r_refdef.view.frustum[5].dist = m[15] + m[14];
5439 #endif
5440 
5441 	if (r_refdef.view.useperspective)
5442 	{
5443 		// calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5444 		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]);
5445 		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]);
5446 		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]);
5447 		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]);
5448 
5449 		// then the normals from the corners relative to origin
5450 		CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5451 		CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5452 		CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5453 		CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5454 
5455 		// in a NORMAL view, forward cross left == up
5456 		// in a REFLECTED view, forward cross left == down
5457 		// so our cross products above need to be adjusted for a left handed coordinate system
5458 		CrossProduct(forward, left, v);
5459 		if(DotProduct(v, up) < 0)
5460 		{
5461 			VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5462 			VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5463 			VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5464 			VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5465 		}
5466 
5467 		// Leaving those out was a mistake, those were in the old code, and they
5468 		// fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5469 		// I couldn't reproduce it after adding those normalizations. --blub
5470 		VectorNormalize(r_refdef.view.frustum[0].normal);
5471 		VectorNormalize(r_refdef.view.frustum[1].normal);
5472 		VectorNormalize(r_refdef.view.frustum[2].normal);
5473 		VectorNormalize(r_refdef.view.frustum[3].normal);
5474 
5475 		// make the corners absolute
5476 		VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5477 		VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5478 		VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5479 		VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5480 
5481 		// one more normal
5482 		VectorCopy(forward, r_refdef.view.frustum[4].normal);
5483 
5484 		r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5485 		r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5486 		r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5487 		r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5488 		r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5489 	}
5490 	else
5491 	{
5492 		VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5493 		VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5494 		VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5495 		VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5496 		VectorCopy(forward, r_refdef.view.frustum[4].normal);
5497 		r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5498 		r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5499 		r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5500 		r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5501 		r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5502 	}
5503 	r_refdef.view.numfrustumplanes = 5;
5504 
5505 	if (r_refdef.view.useclipplane)
5506 	{
5507 		r_refdef.view.numfrustumplanes = 6;
5508 		r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5509 	}
5510 
5511 	for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5512 		PlaneClassify(r_refdef.view.frustum + i);
5513 
5514 	// LordHavoc: note to all quake engine coders, Quake had a special case
5515 	// for 90 degrees which assumed a square view (wrong), so I removed it,
5516 	// Quake2 has it disabled as well.
5517 
5518 	// rotate R_VIEWFORWARD right by FOV_X/2 degrees
5519 	//RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5520 	//r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5521 	//PlaneClassify(&frustum[0]);
5522 
5523 	// rotate R_VIEWFORWARD left by FOV_X/2 degrees
5524 	//RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5525 	//r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5526 	//PlaneClassify(&frustum[1]);
5527 
5528 	// rotate R_VIEWFORWARD up by FOV_X/2 degrees
5529 	//RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5530 	//r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5531 	//PlaneClassify(&frustum[2]);
5532 
5533 	// rotate R_VIEWFORWARD down by FOV_X/2 degrees
5534 	//RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5535 	//r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5536 	//PlaneClassify(&frustum[3]);
5537 
5538 	// nearclip plane
5539 	//VectorCopy(forward, r_refdef.view.frustum[4].normal);
5540 	//r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5541 	//PlaneClassify(&frustum[4]);
5542 }
5543 
R_View_UpdateWithScissor(const int * myscissor)5544 static void R_View_UpdateWithScissor(const int *myscissor)
5545 {
5546 	R_Main_ResizeViewCache();
5547 	R_View_SetFrustum(myscissor);
5548 	R_View_WorldVisibility(r_refdef.view.useclipplane);
5549 	R_View_UpdateEntityVisible();
5550 }
5551 
R_View_Update(void)5552 static void R_View_Update(void)
5553 {
5554 	R_Main_ResizeViewCache();
5555 	R_View_SetFrustum(NULL);
5556 	R_View_WorldVisibility(r_refdef.view.useclipplane);
5557 	R_View_UpdateEntityVisible();
5558 }
5559 
5560 float viewscalefpsadjusted = 1.0f;
5561 
R_GetScaledViewSize(int width,int height,int * outwidth,int * outheight)5562 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5563 {
5564 	float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5565 	scale = bound(0.03125f, scale, 1.0f);
5566 	*outwidth = (int)ceil(width * scale);
5567 	*outheight = (int)ceil(height * scale);
5568 }
5569 
R_SetupView(qboolean allowwaterclippingplane,int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)5570 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5571 {
5572 	const float *customclipplane = NULL;
5573 	float plane[4];
5574 	int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5575 	if (r_refdef.view.useclipplane && allowwaterclippingplane)
5576 	{
5577 		// LordHavoc: couldn't figure out how to make this approach the
5578 		vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5579 		vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5580 		if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5581 			dist = r_refdef.view.clipplane.dist;
5582 		plane[0] = r_refdef.view.clipplane.normal[0];
5583 		plane[1] = r_refdef.view.clipplane.normal[1];
5584 		plane[2] = r_refdef.view.clipplane.normal[2];
5585 		plane[3] = -dist;
5586 		if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5587 	}
5588 
5589 	//rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5590 	rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5591 
5592 	R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5593 	if (!r_refdef.view.useperspective)
5594 		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);
5595 	else if (vid.stencil && r_useinfinitefarclip.integer)
5596 		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);
5597 	else
5598 		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);
5599 	R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5600 	R_SetViewport(&r_refdef.view.viewport);
5601 	if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5602 	{
5603 		matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5604 		float screenplane[4];
5605 		Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5606 		Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5607 		Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5608 		Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5609 		DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5610 	}
5611 }
5612 
R_EntityMatrix(const matrix4x4_t * matrix)5613 void R_EntityMatrix(const matrix4x4_t *matrix)
5614 {
5615 	if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5616 	{
5617 		gl_modelmatrixchanged = false;
5618 		gl_modelmatrix = *matrix;
5619 		Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5620 		Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5621 		Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5622 		Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5623 		CHECKGLERROR
5624 		switch(vid.renderpath)
5625 		{
5626 		case RENDERPATH_D3D9:
5627 #ifdef SUPPORTD3D
5628 			hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5629 			hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5630 #endif
5631 			break;
5632 		case RENDERPATH_D3D10:
5633 			Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5634 			break;
5635 		case RENDERPATH_D3D11:
5636 			Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5637 			break;
5638 		case RENDERPATH_GL11:
5639 		case RENDERPATH_GL13:
5640 		case RENDERPATH_GLES1:
5641 #ifndef USE_GLES2
5642 			qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5643 #endif
5644 			break;
5645 		case RENDERPATH_SOFT:
5646 			DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5647 			DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5648 			break;
5649 		case RENDERPATH_GL20:
5650 		case RENDERPATH_GLES2:
5651 			if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5652 			if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5653 			break;
5654 		}
5655 	}
5656 }
5657 
R_ResetViewRendering2D_Common(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture,float x2,float y2)5658 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5659 {
5660 	r_viewport_t viewport;
5661 
5662 	CHECKGLERROR
5663 
5664 	// GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5665 	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);
5666 	R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5667 	R_SetViewport(&viewport);
5668 	GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5669 	GL_Color(1, 1, 1, 1);
5670 	GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5671 	GL_BlendFunc(GL_ONE, GL_ZERO);
5672 	GL_ScissorTest(false);
5673 	GL_DepthMask(false);
5674 	GL_DepthRange(0, 1);
5675 	GL_DepthTest(false);
5676 	GL_DepthFunc(GL_LEQUAL);
5677 	R_EntityMatrix(&identitymatrix);
5678 	R_Mesh_ResetTextureState();
5679 	GL_PolygonOffset(0, 0);
5680 	R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5681 	switch(vid.renderpath)
5682 	{
5683 	case RENDERPATH_GL11:
5684 	case RENDERPATH_GL13:
5685 	case RENDERPATH_GL20:
5686 	case RENDERPATH_GLES1:
5687 	case RENDERPATH_GLES2:
5688 		qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5689 		break;
5690 	case RENDERPATH_D3D9:
5691 	case RENDERPATH_D3D10:
5692 	case RENDERPATH_D3D11:
5693 	case RENDERPATH_SOFT:
5694 		break;
5695 	}
5696 	GL_CullFace(GL_NONE);
5697 
5698 	CHECKGLERROR
5699 }
5700 
R_ResetViewRendering2D(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)5701 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5702 {
5703 	DrawQ_Finish();
5704 
5705 	R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5706 }
5707 
R_ResetViewRendering3D(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)5708 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5709 {
5710 	DrawQ_Finish();
5711 
5712 	R_SetupView(true, fbo, depthtexture, colortexture);
5713 	GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5714 	GL_Color(1, 1, 1, 1);
5715 	GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5716 	GL_BlendFunc(GL_ONE, GL_ZERO);
5717 	GL_ScissorTest(true);
5718 	GL_DepthMask(true);
5719 	GL_DepthRange(0, 1);
5720 	GL_DepthTest(true);
5721 	GL_DepthFunc(GL_LEQUAL);
5722 	R_EntityMatrix(&identitymatrix);
5723 	R_Mesh_ResetTextureState();
5724 	GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5725 	R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5726 	switch(vid.renderpath)
5727 	{
5728 	case RENDERPATH_GL11:
5729 	case RENDERPATH_GL13:
5730 	case RENDERPATH_GL20:
5731 	case RENDERPATH_GLES1:
5732 	case RENDERPATH_GLES2:
5733 		qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5734 		break;
5735 	case RENDERPATH_D3D9:
5736 	case RENDERPATH_D3D10:
5737 	case RENDERPATH_D3D11:
5738 	case RENDERPATH_SOFT:
5739 		break;
5740 	}
5741 	GL_CullFace(r_refdef.view.cullface_back);
5742 }
5743 
5744 /*
5745 ================
5746 R_RenderView_UpdateViewVectors
5747 ================
5748 */
R_RenderView_UpdateViewVectors(void)5749 void R_RenderView_UpdateViewVectors(void)
5750 {
5751 	// break apart the view matrix into vectors for various purposes
5752 	// it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5753 	// however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5754 	Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5755 	VectorNegate(r_refdef.view.left, r_refdef.view.right);
5756 	// make an inverted copy of the view matrix for tracking sprites
5757 	Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5758 }
5759 
5760 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5761 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5762 
R_Water_StartFrame(void)5763 static void R_Water_StartFrame(void)
5764 {
5765 	int i;
5766 	int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5767 	r_waterstate_waterplane_t *p;
5768 	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;
5769 
5770 	if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5771 		return;
5772 
5773 	switch(vid.renderpath)
5774 	{
5775 	case RENDERPATH_GL20:
5776 	case RENDERPATH_D3D9:
5777 	case RENDERPATH_D3D10:
5778 	case RENDERPATH_D3D11:
5779 	case RENDERPATH_SOFT:
5780 	case RENDERPATH_GLES2:
5781 		break;
5782 	case RENDERPATH_GL11:
5783 	case RENDERPATH_GL13:
5784 	case RENDERPATH_GLES1:
5785 		return;
5786 	}
5787 
5788 	// set waterwidth and waterheight to the water resolution that will be
5789 	// used (often less than the screen resolution for faster rendering)
5790 	R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5791 
5792 	// calculate desired texture sizes
5793 	// can't use water if the card does not support the texture size
5794 	if (!r_water.integer || r_showsurfaces.integer)
5795 		texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5796 	else if (vid.support.arb_texture_non_power_of_two)
5797 	{
5798 		texturewidth = waterwidth;
5799 		textureheight = waterheight;
5800 		camerawidth = waterwidth;
5801 		cameraheight = waterheight;
5802 	}
5803 	else
5804 	{
5805 		for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5806 		for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5807 		for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5808 		for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5809 	}
5810 
5811 	// allocate textures as needed
5812 	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))
5813 	{
5814 		r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5815 		for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5816 		{
5817 			if (p->texture_refraction)
5818 				R_FreeTexture(p->texture_refraction);
5819 			p->texture_refraction = NULL;
5820 			if (p->fbo_refraction)
5821 				R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5822 			p->fbo_refraction = 0;
5823 			if (p->texture_reflection)
5824 				R_FreeTexture(p->texture_reflection);
5825 			p->texture_reflection = NULL;
5826 			if (p->fbo_reflection)
5827 				R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5828 			p->fbo_reflection = 0;
5829 			if (p->texture_camera)
5830 				R_FreeTexture(p->texture_camera);
5831 			p->texture_camera = NULL;
5832 			if (p->fbo_camera)
5833 				R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5834 			p->fbo_camera = 0;
5835 		}
5836 		memset(&r_fb.water, 0, sizeof(r_fb.water));
5837 		r_fb.water.texturewidth = texturewidth;
5838 		r_fb.water.textureheight = textureheight;
5839 		r_fb.water.camerawidth = camerawidth;
5840 		r_fb.water.cameraheight = cameraheight;
5841 	}
5842 
5843 	if (r_fb.water.texturewidth)
5844 	{
5845 		int scaledwidth, scaledheight;
5846 
5847 		r_fb.water.enabled = true;
5848 
5849 		// water resolution is usually reduced
5850 		r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5851 		r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5852 		R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5853 
5854 		// set up variables that will be used in shader setup
5855 		r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5856 		r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5857 		r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5858 		r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5859 	}
5860 
5861 	r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5862 	r_fb.water.numwaterplanes = 0;
5863 }
5864 
R_Water_AddWaterPlane(msurface_t * surface,int entno)5865 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5866 {
5867 	int planeindex, bestplaneindex, vertexindex;
5868 	vec3_t mins, maxs, normal, center, v, n;
5869 	vec_t planescore, bestplanescore;
5870 	mplane_t plane;
5871 	r_waterstate_waterplane_t *p;
5872 	texture_t *t = R_GetCurrentTexture(surface->texture);
5873 
5874 	rsurface.texture = t;
5875 	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5876 	// if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5877 	if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5878 		return;
5879 	// average the vertex normals, find the surface bounds (after deformvertexes)
5880 	Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5881 	Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5882 	VectorCopy(n, normal);
5883 	VectorCopy(v, mins);
5884 	VectorCopy(v, maxs);
5885 	for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5886 	{
5887 		Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5888 		Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5889 		VectorAdd(normal, n, normal);
5890 		mins[0] = min(mins[0], v[0]);
5891 		mins[1] = min(mins[1], v[1]);
5892 		mins[2] = min(mins[2], v[2]);
5893 		maxs[0] = max(maxs[0], v[0]);
5894 		maxs[1] = max(maxs[1], v[1]);
5895 		maxs[2] = max(maxs[2], v[2]);
5896 	}
5897 	VectorNormalize(normal);
5898 	VectorMAM(0.5f, mins, 0.5f, maxs, center);
5899 
5900 	VectorCopy(normal, plane.normal);
5901 	VectorNormalize(plane.normal);
5902 	plane.dist = DotProduct(center, plane.normal);
5903 	PlaneClassify(&plane);
5904 	if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5905 	{
5906 		// skip backfaces (except if nocullface is set)
5907 //		if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5908 //			return;
5909 		VectorNegate(plane.normal, plane.normal);
5910 		plane.dist *= -1;
5911 		PlaneClassify(&plane);
5912 	}
5913 
5914 
5915 	// find a matching plane if there is one
5916 	bestplaneindex = -1;
5917 	bestplanescore = 1048576.0f;
5918 	for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5919 	{
5920 		if(p->camera_entity == t->camera_entity)
5921 		{
5922 			planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5923 			if (bestplaneindex < 0 || bestplanescore > planescore)
5924 			{
5925 				bestplaneindex = planeindex;
5926 				bestplanescore = planescore;
5927 			}
5928 		}
5929 	}
5930 	planeindex = bestplaneindex;
5931 
5932 	// if this surface does not fit any known plane rendered this frame, add one
5933 	if (planeindex < 0 || bestplanescore > 0.001f)
5934 	{
5935 		if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5936 		{
5937 			// store the new plane
5938 			planeindex = r_fb.water.numwaterplanes++;
5939 			p = r_fb.water.waterplanes + planeindex;
5940 			p->plane = plane;
5941 			// clear materialflags and pvs
5942 			p->materialflags = 0;
5943 			p->pvsvalid = false;
5944 			p->camera_entity = t->camera_entity;
5945 			VectorCopy(mins, p->mins);
5946 			VectorCopy(maxs, p->maxs);
5947 		}
5948 		else
5949 		{
5950 			// We're totally screwed.
5951 			return;
5952 		}
5953 	}
5954 	else
5955 	{
5956 		// merge mins/maxs when we're adding this surface to the plane
5957 		p = r_fb.water.waterplanes + planeindex;
5958 		p->mins[0] = min(p->mins[0], mins[0]);
5959 		p->mins[1] = min(p->mins[1], mins[1]);
5960 		p->mins[2] = min(p->mins[2], mins[2]);
5961 		p->maxs[0] = max(p->maxs[0], maxs[0]);
5962 		p->maxs[1] = max(p->maxs[1], maxs[1]);
5963 		p->maxs[2] = max(p->maxs[2], maxs[2]);
5964 	}
5965 	// merge this surface's materialflags into the waterplane
5966 	p->materialflags |= t->currentmaterialflags;
5967 	if(!(p->materialflags & MATERIALFLAG_CAMERA))
5968 	{
5969 		// merge this surface's PVS into the waterplane
5970 		if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5971 		 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5972 		{
5973 			r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5974 			p->pvsvalid = true;
5975 		}
5976 	}
5977 }
5978 
5979 extern cvar_t r_drawparticles;
5980 extern cvar_t r_drawdecals;
5981 
R_Water_ProcessPlanes(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)5982 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5983 {
5984 	int myscissor[4];
5985 	r_refdef_view_t originalview;
5986 	r_refdef_view_t myview;
5987 	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;
5988 	r_waterstate_waterplane_t *p;
5989 	vec3_t visorigin;
5990 	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;
5991 	char vabuf[1024];
5992 
5993 	originalview = r_refdef.view;
5994 
5995 	// lowquality hack, temporarily shut down some cvars and restore afterwards
5996 	qualityreduction = r_water_lowquality.integer;
5997 	if (qualityreduction > 0)
5998 	{
5999 		if (qualityreduction >= 1)
6000 		{
6001 			old_r_shadows = r_shadows.integer;
6002 			old_r_worldrtlight = r_shadow_realtime_world.integer;
6003 			old_r_dlight = r_shadow_realtime_dlight.integer;
6004 			Cvar_SetValueQuick(&r_shadows, 0);
6005 			Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6006 			Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6007 		}
6008 		if (qualityreduction >= 2)
6009 		{
6010 			old_r_dynamic = r_dynamic.integer;
6011 			old_r_particles = r_drawparticles.integer;
6012 			old_r_decals = r_drawdecals.integer;
6013 			Cvar_SetValueQuick(&r_dynamic, 0);
6014 			Cvar_SetValueQuick(&r_drawparticles, 0);
6015 			Cvar_SetValueQuick(&r_drawdecals, 0);
6016 		}
6017 	}
6018 
6019 	// make sure enough textures are allocated
6020 	for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6021 	{
6022 		if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6023 			continue;
6024 		if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6025 		{
6026 			if (!p->texture_refraction)
6027 				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);
6028 			if (!p->texture_refraction)
6029 				goto error;
6030 			if (usewaterfbo)
6031 			{
6032 				if (r_fb.water.depthtexture == NULL)
6033 					r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034 				if (p->fbo_refraction == 0)
6035 					p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6036 			}
6037 		}
6038 		else if (p->materialflags & MATERIALFLAG_CAMERA)
6039 		{
6040 			if (!p->texture_camera)
6041 				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);
6042 			if (!p->texture_camera)
6043 				goto error;
6044 			if (usewaterfbo)
6045 			{
6046 				if (r_fb.water.depthtexture == NULL)
6047 					r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6048 				if (p->fbo_camera == 0)
6049 					p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6050 			}
6051 		}
6052 
6053 		if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6054 		{
6055 			if (!p->texture_reflection)
6056 				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);
6057 			if (!p->texture_reflection)
6058 				goto error;
6059 			if (usewaterfbo)
6060 			{
6061 				if (r_fb.water.depthtexture == NULL)
6062 					r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6063 				if (p->fbo_reflection == 0)
6064 					p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6065 			}
6066 		}
6067 	}
6068 
6069 	// render views
6070 	r_refdef.view = originalview;
6071 	r_refdef.view.showdebug = false;
6072 	r_refdef.view.width = r_fb.water.waterwidth;
6073 	r_refdef.view.height = r_fb.water.waterheight;
6074 	r_refdef.view.useclipplane = true;
6075 	myview = r_refdef.view;
6076 	r_fb.water.renderingscene = true;
6077 	for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078 	{
6079 		if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6080 			continue;
6081 		if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6082 		{
6083 			r_refdef.view = myview;
6084 			if(r_water_scissormode.integer)
6085 			{
6086 				R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6087 				if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6088 					continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6089 			}
6090 
6091 			// render reflected scene and copy into texture
6092 			Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6093 			// update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6094 			Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6095 			r_refdef.view.clipplane = p->plane;
6096 			// reverse the cullface settings for this render
6097 			r_refdef.view.cullface_front = GL_FRONT;
6098 			r_refdef.view.cullface_back = GL_BACK;
6099 			if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6100 			{
6101 				r_refdef.view.usecustompvs = true;
6102 				if (p->pvsvalid)
6103 					memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6104 				else
6105 					memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6106 			}
6107 
6108 			r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6109 			R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6110 			R_ClearScreen(r_refdef.fogenabled);
6111 			if(r_water_scissormode.integer & 2)
6112 				R_View_UpdateWithScissor(myscissor);
6113 			else
6114 				R_View_Update();
6115 			R_AnimCache_CacheVisibleEntities();
6116 			if(r_water_scissormode.integer & 1)
6117 				GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6118 			R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6119 
6120 			if (!p->fbo_reflection)
6121 				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);
6122 			r_fb.water.hideplayer = false;
6123 		}
6124 
6125 		// render the normal view scene and copy into texture
6126 		// (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)
6127 		if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6128 		{
6129 			r_refdef.view = myview;
6130 			if(r_water_scissormode.integer)
6131 			{
6132 				R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6133 				if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6134 					continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6135 			}
6136 
6137 			r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6138 
6139 			r_refdef.view.clipplane = p->plane;
6140 			VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6141 			r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6142 
6143 			if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6144 			{
6145 				// we need to perform a matrix transform to render the view... so let's get the transformation matrix
6146 				r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6147 				CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6148 				R_RenderView_UpdateViewVectors();
6149 				if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6150 				{
6151 					r_refdef.view.usecustompvs = true;
6152 					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);
6153 				}
6154 			}
6155 
6156 			PlaneClassify(&r_refdef.view.clipplane);
6157 
6158 			R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6159 			R_ClearScreen(r_refdef.fogenabled);
6160 			if(r_water_scissormode.integer & 2)
6161 				R_View_UpdateWithScissor(myscissor);
6162 			else
6163 				R_View_Update();
6164 			R_AnimCache_CacheVisibleEntities();
6165 			if(r_water_scissormode.integer & 1)
6166 				GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6167 			R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6168 
6169 			if (!p->fbo_refraction)
6170 				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);
6171 			r_fb.water.hideplayer = false;
6172 		}
6173 		else if (p->materialflags & MATERIALFLAG_CAMERA)
6174 		{
6175 			r_refdef.view = myview;
6176 
6177 			r_refdef.view.clipplane = p->plane;
6178 			VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6179 			r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6180 
6181 			r_refdef.view.width = r_fb.water.camerawidth;
6182 			r_refdef.view.height = r_fb.water.cameraheight;
6183 			r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6184 			r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6185 			r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6186 			r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6187 
6188 			if(p->camera_entity)
6189 			{
6190 				// we need to perform a matrix transform to render the view... so let's get the transformation matrix
6191 				CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6192 			}
6193 
6194 			// note: all of the view is used for displaying... so
6195 			// there is no use in scissoring
6196 
6197 			// reverse the cullface settings for this render
6198 			r_refdef.view.cullface_front = GL_FRONT;
6199 			r_refdef.view.cullface_back = GL_BACK;
6200 			// also reverse the view matrix
6201 			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
6202 			R_RenderView_UpdateViewVectors();
6203 			if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6204 			{
6205 				r_refdef.view.usecustompvs = true;
6206 				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);
6207 			}
6208 
6209 			// camera needs no clipplane
6210 			r_refdef.view.useclipplane = false;
6211 
6212 			PlaneClassify(&r_refdef.view.clipplane);
6213 
6214 			r_fb.water.hideplayer = false;
6215 
6216 			R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6217 			R_ClearScreen(r_refdef.fogenabled);
6218 			R_View_Update();
6219 			R_AnimCache_CacheVisibleEntities();
6220 			R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6221 
6222 			if (!p->fbo_camera)
6223 				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);
6224 			r_fb.water.hideplayer = false;
6225 		}
6226 
6227 	}
6228 	if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6229 	r_fb.water.renderingscene = false;
6230 	r_refdef.view = originalview;
6231 	R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6232 	if (!r_fb.water.depthtexture)
6233 		R_ClearScreen(r_refdef.fogenabled);
6234 	R_View_Update();
6235 	R_AnimCache_CacheVisibleEntities();
6236 	goto finish;
6237 error:
6238 	r_refdef.view = originalview;
6239 	r_fb.water.renderingscene = false;
6240 	Cvar_SetValueQuick(&r_water, 0);
6241 	Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6242 finish:
6243 	// lowquality hack, restore cvars
6244 	if (qualityreduction > 0)
6245 	{
6246 		if (qualityreduction >= 1)
6247 		{
6248 			Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6249 			Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6250 			Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6251 		}
6252 		if (qualityreduction >= 2)
6253 		{
6254 			Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6255 			Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6256 			Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6257 		}
6258 	}
6259 }
6260 
R_Bloom_StartFrame(void)6261 static void R_Bloom_StartFrame(void)
6262 {
6263 	int i;
6264 	int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6265 	int viewwidth, viewheight;
6266 	qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6267 	textype_t textype = TEXTYPE_COLORBUFFER;
6268 
6269 	switch (vid.renderpath)
6270 	{
6271 	case RENDERPATH_GL20:
6272 		r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273 		if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6274 		{
6275 			if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6276 			if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6277 		}
6278 		break;
6279 	case RENDERPATH_GL11:
6280 	case RENDERPATH_GL13:
6281 	case RENDERPATH_GLES1:
6282 		return; // don't bother
6283 	case RENDERPATH_GLES2:
6284 	case RENDERPATH_D3D9:
6285 	case RENDERPATH_D3D10:
6286 	case RENDERPATH_D3D11:
6287 		r_fb.usedepthtextures = false;
6288 		break;
6289 	case RENDERPATH_SOFT:
6290 		r_fb.usedepthtextures = true;
6291 		break;
6292 	}
6293 
6294 	if (r_viewscale_fpsscaling.integer)
6295 	{
6296 		double actualframetime;
6297 		double targetframetime;
6298 		double adjust;
6299 		actualframetime = r_refdef.lastdrawscreentime;
6300 		targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6301 		adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6302 		adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6303 		if (r_viewscale_fpsscaling_stepsize.value > 0)
6304 			adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6305 		viewscalefpsadjusted += adjust;
6306 		viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6307 	}
6308 	else
6309 		viewscalefpsadjusted = 1.0f;
6310 
6311 	R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6312 
6313 	switch(vid.renderpath)
6314 	{
6315 	case RENDERPATH_GL20:
6316 	case RENDERPATH_D3D9:
6317 	case RENDERPATH_D3D10:
6318 	case RENDERPATH_D3D11:
6319 	case RENDERPATH_SOFT:
6320 	case RENDERPATH_GLES2:
6321 		break;
6322 	case RENDERPATH_GL11:
6323 	case RENDERPATH_GL13:
6324 	case RENDERPATH_GLES1:
6325 		return;
6326 	}
6327 
6328 	// set bloomwidth and bloomheight to the bloom resolution that will be
6329 	// used (often less than the screen resolution for faster rendering)
6330 	r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6331 	r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6332 	r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6333 	r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6334 	r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6335 
6336 	// calculate desired texture sizes
6337 	if (vid.support.arb_texture_non_power_of_two)
6338 	{
6339 		screentexturewidth = vid.width;
6340 		screentextureheight = vid.height;
6341 		bloomtexturewidth = r_fb.bloomwidth;
6342 		bloomtextureheight = r_fb.bloomheight;
6343 	}
6344 	else
6345 	{
6346 		for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6347 		for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6348 		for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6349 		for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6350 	}
6351 
6352 	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))
6353 	{
6354 		Cvar_SetValueQuick(&r_bloom, 0);
6355 		Cvar_SetValueQuick(&r_motionblur, 0);
6356 		Cvar_SetValueQuick(&r_damageblur, 0);
6357 	}
6358 
6359 	if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6360 	 && !r_bloom.integer
6361 	 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6362 	 && !useviewfbo
6363 	 && r_viewscale.value == 1.0f
6364 	 && !r_viewscale_fpsscaling.integer)
6365 		screentexturewidth = screentextureheight = 0;
6366 	if (!r_bloom.integer)
6367 		bloomtexturewidth = bloomtextureheight = 0;
6368 
6369 	// allocate textures as needed
6370 	if (r_fb.screentexturewidth != screentexturewidth
6371 	 || r_fb.screentextureheight != screentextureheight
6372 	 || r_fb.bloomtexturewidth != bloomtexturewidth
6373 	 || r_fb.bloomtextureheight != bloomtextureheight
6374 	 || r_fb.textype != textype
6375 	 || useviewfbo != (r_fb.fbo != 0))
6376 	{
6377 		for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6378 		{
6379 			if (r_fb.bloomtexture[i])
6380 				R_FreeTexture(r_fb.bloomtexture[i]);
6381 			r_fb.bloomtexture[i] = NULL;
6382 
6383 			if (r_fb.bloomfbo[i])
6384 				R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6385 			r_fb.bloomfbo[i] = 0;
6386 		}
6387 
6388 		if (r_fb.fbo)
6389 			R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6390 		r_fb.fbo = 0;
6391 
6392 		if (r_fb.colortexture)
6393 			R_FreeTexture(r_fb.colortexture);
6394 		r_fb.colortexture = NULL;
6395 
6396 		if (r_fb.depthtexture)
6397 			R_FreeTexture(r_fb.depthtexture);
6398 		r_fb.depthtexture = NULL;
6399 
6400 		if (r_fb.ghosttexture)
6401 			R_FreeTexture(r_fb.ghosttexture);
6402 		r_fb.ghosttexture = NULL;
6403 
6404 		r_fb.screentexturewidth = screentexturewidth;
6405 		r_fb.screentextureheight = screentextureheight;
6406 		r_fb.bloomtexturewidth = bloomtexturewidth;
6407 		r_fb.bloomtextureheight = bloomtextureheight;
6408 		r_fb.textype = textype;
6409 
6410 		if (r_fb.screentexturewidth && r_fb.screentextureheight)
6411 		{
6412 			if (r_motionblur.value > 0 || r_damageblur.value > 0)
6413 				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);
6414 			r_fb.ghosttexture_valid = false;
6415 			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);
6416 			if (useviewfbo)
6417 			{
6418 				r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6419 				r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6420 				R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6421 			}
6422 		}
6423 
6424 		if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6425 		{
6426 			for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6427 			{
6428 				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);
6429 				if (useviewfbo)
6430 					r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6431 			}
6432 		}
6433 	}
6434 
6435 	// bloom texture is a different resolution
6436 	r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6437 	r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6438 	r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6439 	r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6440 	r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6441 
6442 	// set up a texcoord array for the full resolution screen image
6443 	// (we have to keep this around to copy back during final render)
6444 	r_fb.screentexcoord2f[0] = 0;
6445 	r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6446 	r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6447 	r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6448 	r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6449 	r_fb.screentexcoord2f[5] = 0;
6450 	r_fb.screentexcoord2f[6] = 0;
6451 	r_fb.screentexcoord2f[7] = 0;
6452 
6453 	if(r_fb.fbo)
6454 	{
6455 		for (i = 1;i < 8;i += 2)
6456 		{
6457 			r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6458 		}
6459 	}
6460 
6461 	// set up a texcoord array for the reduced resolution bloom image
6462 	// (which will be additive blended over the screen image)
6463 	r_fb.bloomtexcoord2f[0] = 0;
6464 	r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6465 	r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6466 	r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6467 	r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6468 	r_fb.bloomtexcoord2f[5] = 0;
6469 	r_fb.bloomtexcoord2f[6] = 0;
6470 	r_fb.bloomtexcoord2f[7] = 0;
6471 
6472 	switch(vid.renderpath)
6473 	{
6474 	case RENDERPATH_GL11:
6475 	case RENDERPATH_GL13:
6476 	case RENDERPATH_GL20:
6477 	case RENDERPATH_SOFT:
6478 	case RENDERPATH_GLES1:
6479 	case RENDERPATH_GLES2:
6480 		break;
6481 	case RENDERPATH_D3D9:
6482 	case RENDERPATH_D3D10:
6483 	case RENDERPATH_D3D11:
6484 		for (i = 0;i < 4;i++)
6485 		{
6486 			r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6487 			r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6488 			r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6489 			r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6490 		}
6491 		break;
6492 	}
6493 
6494 	R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6495 
6496 	if (r_fb.fbo)
6497 		r_refdef.view.clear = true;
6498 }
6499 
R_Bloom_MakeTexture(void)6500 static void R_Bloom_MakeTexture(void)
6501 {
6502 	int x, range, dir;
6503 	float xoffset, yoffset, r, brighten;
6504 	rtexture_t *intex;
6505 	float colorscale = r_bloom_colorscale.value;
6506 
6507 	r_refdef.stats[r_stat_bloom]++;
6508 
6509 #if 0
6510     // this copy is unnecessary since it happens in R_BlendView already
6511 	if (!r_fb.fbo)
6512 	{
6513 		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);
6514 		r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6515 	}
6516 #endif
6517 
6518 	// scale down screen texture to the bloom texture size
6519 	CHECKGLERROR
6520 	r_fb.bloomindex = 0;
6521 	R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6522 	R_SetViewport(&r_fb.bloomviewport);
6523 	GL_CullFace(GL_NONE);
6524 	GL_DepthTest(false);
6525 	GL_BlendFunc(GL_ONE, GL_ZERO);
6526 	GL_Color(colorscale, colorscale, colorscale, 1);
6527 	// 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...
6528 	switch(vid.renderpath)
6529 	{
6530 	case RENDERPATH_GL11:
6531 	case RENDERPATH_GL13:
6532 	case RENDERPATH_GL20:
6533 	case RENDERPATH_GLES1:
6534 	case RENDERPATH_GLES2:
6535 	case RENDERPATH_SOFT:
6536 		R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6537 		break;
6538 	case RENDERPATH_D3D9:
6539 	case RENDERPATH_D3D10:
6540 	case RENDERPATH_D3D11:
6541 		R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6542 		break;
6543 	}
6544 	// TODO: do boxfilter scale-down in shader?
6545 	R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6546 	R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547 	r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6548 
6549 	// we now have a properly scaled bloom image
6550 	if (!r_fb.bloomfbo[r_fb.bloomindex])
6551 	{
6552 		// copy it into the bloom texture
6553 		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);
6554 		r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6555 	}
6556 
6557 	// multiply bloom image by itself as many times as desired
6558 	for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6559 	{
6560 		intex = r_fb.bloomtexture[r_fb.bloomindex];
6561 		r_fb.bloomindex ^= 1;
6562 		R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6563 		x *= 2;
6564 		r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6565 		if (!r_fb.bloomfbo[r_fb.bloomindex])
6566 		{
6567 			GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6568 			GL_Color(r,r,r,1); // apply fix factor
6569 		}
6570 		else
6571 		{
6572 			if(x <= 2)
6573 				GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6574 			GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6575 			GL_Color(1,1,1,1); // no fix factor supported here
6576 		}
6577 		R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6578 		R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6579 		R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6580 		r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6581 
6582 		if (!r_fb.bloomfbo[r_fb.bloomindex])
6583 		{
6584 			// copy the darkened image to a texture
6585 			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);
6586 			r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6587 		}
6588 	}
6589 
6590 	range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6591 	brighten = r_bloom_brighten.value;
6592 	brighten = sqrt(brighten);
6593 	if(range >= 1)
6594 		brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6595 
6596 	for (dir = 0;dir < 2;dir++)
6597 	{
6598 		intex = r_fb.bloomtexture[r_fb.bloomindex];
6599 		r_fb.bloomindex ^= 1;
6600 		R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6601 		// blend on at multiple vertical offsets to achieve a vertical blur
6602 		// TODO: do offset blends using GLSL
6603 		// TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6604 		GL_BlendFunc(GL_ONE, GL_ZERO);
6605 		R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6606 		for (x = -range;x <= range;x++)
6607 		{
6608 			if (!dir){xoffset = 0;yoffset = x;}
6609 			else {xoffset = x;yoffset = 0;}
6610 			xoffset /= (float)r_fb.bloomtexturewidth;
6611 			yoffset /= (float)r_fb.bloomtextureheight;
6612 			// compute a texcoord array with the specified x and y offset
6613 			r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6614 			r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6615 			r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6616 			r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6617 			r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6618 			r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6619 			r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6620 			r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6621 			// this r value looks like a 'dot' particle, fading sharply to
6622 			// black at the edges
6623 			// (probably not realistic but looks good enough)
6624 			//r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6625 			//r = brighten/(range*2+1);
6626 			r = brighten / (range * 2 + 1);
6627 			if(range >= 1)
6628 				r *= (1 - x*x/(float)(range*range));
6629 			GL_Color(r, r, r, 1);
6630 			R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6631 			R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6632 			r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6633 			GL_BlendFunc(GL_ONE, GL_ONE);
6634 		}
6635 
6636 		if (!r_fb.bloomfbo[r_fb.bloomindex])
6637 		{
6638 			// copy the vertically or horizontally blurred bloom view to a texture
6639 			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);
6640 			r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6641 		}
6642 	}
6643 }
6644 
R_BlendView(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)6645 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6646 {
6647 	dpuint64 permutation;
6648 	float uservecs[4][4];
6649 
6650 	R_EntityMatrix(&identitymatrix);
6651 
6652 	switch (vid.renderpath)
6653 	{
6654 	case RENDERPATH_GL20:
6655 	case RENDERPATH_D3D9:
6656 	case RENDERPATH_D3D10:
6657 	case RENDERPATH_D3D11:
6658 	case RENDERPATH_SOFT:
6659 	case RENDERPATH_GLES2:
6660 		permutation =
6661 			  (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6662 			| (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6663 			| (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6664 			| (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6665 			| ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6666 
6667 		if (r_fb.colortexture)
6668 		{
6669 			if (!r_fb.fbo)
6670 			{
6671 				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);
6672 				r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6673 			}
6674 
6675 			if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6676 			{
6677 				// declare variables
6678 				float blur_factor, blur_mouseaccel, blur_velocity;
6679 				static float blur_average;
6680 				static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6681 
6682 				// set a goal for the factoring
6683 				blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6684 					/ max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6685 				blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6686 					/ max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6687 				blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6688 					+ (blur_mouseaccel * r_motionblur_mousefactor.value));
6689 
6690 				// from the goal, pick an averaged value between goal and last value
6691 				cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6692 				blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6693 
6694 				// enforce minimum amount of blur
6695 				blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6696 
6697 				//Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6698 
6699 				// calculate values into a standard alpha
6700 				cl.motionbluralpha = 1 - exp(-
6701 						(
6702 						 (r_motionblur.value * blur_factor / 80)
6703 						 +
6704 						 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6705 						)
6706 						/
6707 						max(0.0001, cl.time - cl.oldtime) // fps independent
6708 					  );
6709 
6710 				// randomization for the blur value to combat persistent ghosting
6711 				cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6712 				cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6713 
6714 				// apply the blur
6715 				R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6716 				if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6717 				{
6718 					GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719 					GL_Color(1, 1, 1, cl.motionbluralpha);
6720 					switch(vid.renderpath)
6721 					{
6722 					case RENDERPATH_GL11:
6723 					case RENDERPATH_GL13:
6724 					case RENDERPATH_GL20:
6725 					case RENDERPATH_GLES1:
6726 					case RENDERPATH_GLES2:
6727 					case RENDERPATH_SOFT:
6728 						R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6729 						break;
6730 					case RENDERPATH_D3D9:
6731 					case RENDERPATH_D3D10:
6732 					case RENDERPATH_D3D11:
6733 						R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6734 						break;
6735 					}
6736 					R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6737 					R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6738 					r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6739 				}
6740 
6741 				// updates old view angles for next pass
6742 				VectorCopy(cl.viewangles, blur_oldangles);
6743 
6744 				// copy view into the ghost texture
6745 				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);
6746 				r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6747 				r_fb.ghosttexture_valid = true;
6748 			}
6749 		}
6750 		else
6751 		{
6752 			// no r_fb.colortexture means we're rendering to the real fb
6753 			// we may still have to do view tint...
6754 			if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6755 			{
6756 				// apply a color tint to the whole view
6757 				R_ResetViewRendering2D(0, NULL, NULL);
6758 				GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6759 				R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6760 				R_SetupShader_Generic_NoTexture(false, true);
6761 				GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6762 				R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6763 			}
6764 			break; // no screen processing, no bloom, skip it
6765 		}
6766 
6767 		if (r_fb.bloomtexture[0])
6768 		{
6769 			// make the bloom texture
6770 			R_Bloom_MakeTexture();
6771 		}
6772 
6773 #if _MSC_VER >= 1400
6774 #define sscanf sscanf_s
6775 #endif
6776 		memset(uservecs, 0, sizeof(uservecs));
6777 		if (r_glsl_postprocess_uservec1_enable.integer)
6778 			sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6779 		if (r_glsl_postprocess_uservec2_enable.integer)
6780 			sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6781 		if (r_glsl_postprocess_uservec3_enable.integer)
6782 			sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6783 		if (r_glsl_postprocess_uservec4_enable.integer)
6784 			sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6785 
6786 		R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6787 		GL_Color(1, 1, 1, 1);
6788 		GL_BlendFunc(GL_ONE, GL_ZERO);
6789 
6790 		switch(vid.renderpath)
6791 		{
6792 		case RENDERPATH_GL20:
6793 		case RENDERPATH_GLES2:
6794 			R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795 			R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6796 			if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6797 			if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6798 			if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6799 			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]);
6800 			if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801 			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]);
6802 			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]);
6803 			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]);
6804 			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]);
6805 			if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6806 			if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6807 			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);
6808 			break;
6809 		case RENDERPATH_D3D9:
6810 #ifdef SUPPORTD3D
6811 			// 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...
6812 			R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6813 			R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6814 			R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6815 			R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6816 			R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6817 			hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6818 			hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6819 			hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6820 			hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6821 			hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6822 			hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6823 			hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6824 			hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6825 			hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6826 #endif
6827 			break;
6828 		case RENDERPATH_D3D10:
6829 			Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6830 			break;
6831 		case RENDERPATH_D3D11:
6832 			Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6833 			break;
6834 		case RENDERPATH_SOFT:
6835 			R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6836 			R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6837 			R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6838 			R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6839 			R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6840 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6841 			DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6842 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6843 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6844 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6845 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6846 			DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6847 			DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6848 			DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6849 			break;
6850 		default:
6851 			break;
6852 		}
6853 		R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854 		r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6855 		break;
6856 	case RENDERPATH_GL11:
6857 	case RENDERPATH_GL13:
6858 	case RENDERPATH_GLES1:
6859 		if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6860 		{
6861 			// apply a color tint to the whole view
6862 			R_ResetViewRendering2D(0, NULL, NULL);
6863 			GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864 			R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865 			R_SetupShader_Generic_NoTexture(false, true);
6866 			GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867 			R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6868 		}
6869 		break;
6870 	}
6871 }
6872 
6873 matrix4x4_t r_waterscrollmatrix;
6874 
R_UpdateFog(void)6875 void R_UpdateFog(void)
6876 {
6877 	// Nehahra fog
6878 	if (gamemode == GAME_NEHAHRA)
6879 	{
6880 		if (gl_fogenable.integer)
6881 		{
6882 			r_refdef.oldgl_fogenable = true;
6883 			r_refdef.fog_density = gl_fogdensity.value;
6884 			r_refdef.fog_red = gl_fogred.value;
6885 			r_refdef.fog_green = gl_foggreen.value;
6886 			r_refdef.fog_blue = gl_fogblue.value;
6887 			r_refdef.fog_alpha = 1;
6888 			r_refdef.fog_start = 0;
6889 			r_refdef.fog_end = gl_skyclip.value;
6890 			r_refdef.fog_height = 1<<30;
6891 			r_refdef.fog_fadedepth = 128;
6892 		}
6893 		else if (r_refdef.oldgl_fogenable)
6894 		{
6895 			r_refdef.oldgl_fogenable = false;
6896 			r_refdef.fog_density = 0;
6897 			r_refdef.fog_red = 0;
6898 			r_refdef.fog_green = 0;
6899 			r_refdef.fog_blue = 0;
6900 			r_refdef.fog_alpha = 0;
6901 			r_refdef.fog_start = 0;
6902 			r_refdef.fog_end = 0;
6903 			r_refdef.fog_height = 1<<30;
6904 			r_refdef.fog_fadedepth = 128;
6905 		}
6906 	}
6907 
6908 	// fog parms
6909 	r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6910 	r_refdef.fog_start = max(0, r_refdef.fog_start);
6911 	r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6912 
6913 	if (r_refdef.fog_density && r_drawfog.integer)
6914 	{
6915 		r_refdef.fogenabled = true;
6916 		// this is the point where the fog reaches 0.9986 alpha, which we
6917 		// consider a good enough cutoff point for the texture
6918 		// (0.9986 * 256 == 255.6)
6919 		if (r_fog_exp2.integer)
6920 			r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6921 		else
6922 			r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6923 		r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6924 		r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6925 		r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6926 		if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6927 			R_BuildFogHeightTexture();
6928 		// fog color was already set
6929 		// update the fog texture
6930 		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)
6931 			R_BuildFogTexture();
6932 		r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6933 		r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6934 	}
6935 	else
6936 		r_refdef.fogenabled = false;
6937 
6938 	// fog color
6939 	if (r_refdef.fog_density)
6940 	{
6941 		r_refdef.fogcolor[0] = r_refdef.fog_red;
6942 		r_refdef.fogcolor[1] = r_refdef.fog_green;
6943 		r_refdef.fogcolor[2] = r_refdef.fog_blue;
6944 
6945 		Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6946 		r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6947 		r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6948 		r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6949 
6950 		{
6951 			vec3_t fogvec;
6952 			VectorCopy(r_refdef.fogcolor, fogvec);
6953 			//   color.rgb *= ContrastBoost * SceneBrightness;
6954 			VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6955 			r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6956 			r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6957 			r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6958 		}
6959 	}
6960 }
6961 
R_UpdateVariables(void)6962 void R_UpdateVariables(void)
6963 {
6964 	R_Textures_Frame();
6965 
6966 	r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6967 
6968 	r_refdef.farclip = r_farclip_base.value;
6969 	if (r_refdef.scene.worldmodel)
6970 		r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6971 	r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6972 
6973 	if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6974 		Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6975 	r_refdef.polygonfactor = 0;
6976 	r_refdef.polygonoffset = 0;
6977 	r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6978 	r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6979 
6980 	r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6981 	r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6982 	r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6983 	r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6984 	r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6985 	if (FAKELIGHT_ENABLED)
6986 	{
6987 		r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6988 	}
6989 	else if (r_refdef.scene.worldmodel)
6990 	{
6991 		r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6992 	}
6993 	if (r_showsurfaces.integer)
6994 	{
6995 		r_refdef.scene.rtworld = false;
6996 		r_refdef.scene.rtworldshadows = false;
6997 		r_refdef.scene.rtdlight = false;
6998 		r_refdef.scene.rtdlightshadows = false;
6999 		r_refdef.scene.lightmapintensity = 0;
7000 	}
7001 
7002 	r_gpuskeletal = false;
7003 	switch(vid.renderpath)
7004 	{
7005 	case RENDERPATH_GL20:
7006 		r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7007 	case RENDERPATH_D3D9:
7008 	case RENDERPATH_D3D10:
7009 	case RENDERPATH_D3D11:
7010 	case RENDERPATH_SOFT:
7011 	case RENDERPATH_GLES2:
7012 		if(!vid_gammatables_trivial)
7013 		{
7014 			if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7015 			{
7016 				// build GLSL gamma texture
7017 #define RAMPWIDTH 256
7018 				unsigned short ramp[RAMPWIDTH * 3];
7019 				unsigned char rampbgr[RAMPWIDTH][4];
7020 				int i;
7021 
7022 				r_texture_gammaramps_serial = vid_gammatables_serial;
7023 
7024 				VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7025 				for(i = 0; i < RAMPWIDTH; ++i)
7026 				{
7027 					rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7028 					rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7029 					rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7030 					rampbgr[i][3] = 0;
7031 				}
7032 				if (r_texture_gammaramps)
7033 				{
7034 					R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7035 				}
7036 				else
7037 				{
7038 					r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7039 				}
7040 			}
7041 		}
7042 		else
7043 		{
7044 			// remove GLSL gamma texture
7045 		}
7046 		break;
7047 	case RENDERPATH_GL11:
7048 	case RENDERPATH_GL13:
7049 	case RENDERPATH_GLES1:
7050 		break;
7051 	}
7052 }
7053 
7054 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7055 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7056 /*
7057 ================
7058 R_SelectScene
7059 ================
7060 */
R_SelectScene(r_refdef_scene_type_t scenetype)7061 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7062 	if( scenetype != r_currentscenetype ) {
7063 		// store the old scenetype
7064 		r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7065 		r_currentscenetype = scenetype;
7066 		// move in the new scene
7067 		r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7068 	}
7069 }
7070 
7071 /*
7072 ================
7073 R_GetScenePointer
7074 ================
7075 */
R_GetScenePointer(r_refdef_scene_type_t scenetype)7076 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7077 {
7078 	// of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7079 	if( scenetype == r_currentscenetype ) {
7080 		return &r_refdef.scene;
7081 	} else {
7082 		return &r_scenes_store[ scenetype ];
7083 	}
7084 }
7085 
R_SortEntities_Compare(const void * ap,const void * bp)7086 static int R_SortEntities_Compare(const void *ap, const void *bp)
7087 {
7088 	const entity_render_t *a = *(const entity_render_t **)ap;
7089 	const entity_render_t *b = *(const entity_render_t **)bp;
7090 
7091 	// 1. compare model
7092 	if(a->model < b->model)
7093 		return -1;
7094 	if(a->model > b->model)
7095 		return +1;
7096 
7097 	// 2. compare skin
7098 	// TODO possibly calculate the REAL skinnum here first using
7099 	// skinscenes?
7100 	if(a->skinnum < b->skinnum)
7101 		return -1;
7102 	if(a->skinnum > b->skinnum)
7103 		return +1;
7104 
7105 	// everything we compared is equal
7106 	return 0;
7107 }
R_SortEntities(void)7108 static void R_SortEntities(void)
7109 {
7110 	// below or equal 2 ents, sorting never gains anything
7111 	if(r_refdef.scene.numentities <= 2)
7112 		return;
7113 	// sort
7114 	qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7115 }
7116 
7117 /*
7118 ================
7119 R_RenderView
7120 ================
7121 */
7122 int dpsoftrast_test;
7123 extern cvar_t r_shadow_bouncegrid;
R_RenderView(void)7124 void R_RenderView(void)
7125 {
7126 	matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7127 	int fbo;
7128 	rtexture_t *depthtexture;
7129 	rtexture_t *colortexture;
7130 
7131 	dpsoftrast_test = r_test.integer;
7132 
7133 	if (r_timereport_active)
7134 		R_TimeReport("start");
7135 	r_textureframe++; // used only by R_GetCurrentTexture
7136 	rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7137 
7138 	if(R_CompileShader_CheckStaticParms())
7139 		R_GLSL_Restart_f();
7140 
7141 	if (!r_drawentities.integer)
7142 		r_refdef.scene.numentities = 0;
7143 	else if (r_sortentities.integer)
7144 		R_SortEntities();
7145 
7146 	R_AnimCache_ClearCache();
7147 
7148 	/* adjust for stereo display */
7149 	if(R_Stereo_Active())
7150 	{
7151 		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);
7152 		Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7153 	}
7154 
7155 	if (r_refdef.view.isoverlay)
7156 	{
7157 		// TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7158 		R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7159 		GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7160 		R_TimeReport("depthclear");
7161 
7162 		r_refdef.view.showdebug = false;
7163 
7164 		r_fb.water.enabled = false;
7165 		r_fb.water.numwaterplanes = 0;
7166 
7167 		R_RenderScene(0, NULL, NULL);
7168 
7169 		r_refdef.view.matrix = originalmatrix;
7170 
7171 		CHECKGLERROR
7172 		return;
7173 	}
7174 
7175 	if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7176 	{
7177 		r_refdef.view.matrix = originalmatrix;
7178 		return;
7179 	}
7180 
7181 	r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7182 
7183 	if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7184 		// in sRGB fallback, behave similar to true sRGB: convert this
7185 		// value from linear to sRGB
7186 		r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7187 
7188 	R_RenderView_UpdateViewVectors();
7189 
7190 	R_Shadow_UpdateWorldLightSelection();
7191 
7192 	R_Bloom_StartFrame();
7193 
7194 	// apply bloom brightness offset
7195 	if(r_fb.bloomtexture[0])
7196 		r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7197 
7198 	R_Water_StartFrame();
7199 
7200 	// now we probably have an fbo to render into
7201 	fbo = r_fb.fbo;
7202 	depthtexture = r_fb.depthtexture;
7203 	colortexture = r_fb.colortexture;
7204 
7205 	CHECKGLERROR
7206 	if (r_timereport_active)
7207 		R_TimeReport("viewsetup");
7208 
7209 	R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7210 
7211 	if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7212 	{
7213 		R_ClearScreen(r_refdef.fogenabled);
7214 		if (r_timereport_active)
7215 			R_TimeReport("viewclear");
7216 	}
7217 	r_refdef.view.clear = true;
7218 
7219 	r_refdef.view.showdebug = true;
7220 
7221 	R_View_Update();
7222 	if (r_timereport_active)
7223 		R_TimeReport("visibility");
7224 
7225 	R_AnimCache_CacheVisibleEntities();
7226 	if (r_timereport_active)
7227 		R_TimeReport("animcache");
7228 
7229 	R_Shadow_UpdateBounceGridTexture();
7230 	if (r_timereport_active && r_shadow_bouncegrid.integer)
7231 		R_TimeReport("bouncegrid");
7232 
7233 	r_fb.water.numwaterplanes = 0;
7234 	if (r_fb.water.enabled)
7235 		R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7236 
7237 	R_RenderScene(fbo, depthtexture, colortexture);
7238 	r_fb.water.numwaterplanes = 0;
7239 
7240 	R_BlendView(fbo, depthtexture, colortexture);
7241 	if (r_timereport_active)
7242 		R_TimeReport("blendview");
7243 
7244 	GL_Scissor(0, 0, vid.width, vid.height);
7245 	GL_ScissorTest(false);
7246 
7247 	r_refdef.view.matrix = originalmatrix;
7248 
7249 	CHECKGLERROR
7250 }
7251 
R_RenderWaterPlanes(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)7252 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7253 {
7254 	if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7255 	{
7256 		r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7257 		if (r_timereport_active)
7258 			R_TimeReport("waterworld");
7259 	}
7260 
7261 	// don't let sound skip if going slow
7262 	if (r_refdef.scene.extraupdate)
7263 		S_ExtraUpdate ();
7264 
7265 	R_DrawModelsAddWaterPlanes();
7266 	if (r_timereport_active)
7267 		R_TimeReport("watermodels");
7268 
7269 	if (r_fb.water.numwaterplanes)
7270 	{
7271 		R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7272 		if (r_timereport_active)
7273 			R_TimeReport("waterscenes");
7274 	}
7275 }
7276 
7277 extern cvar_t cl_locs_show;
7278 static void R_DrawLocs(void);
7279 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7280 static void R_DrawModelDecals(void);
7281 extern cvar_t cl_decals_newsystem;
7282 extern qboolean r_shadow_usingdeferredprepass;
7283 extern int r_shadow_shadowmapatlas_modelshadows_size;
R_RenderScene(int fbo,rtexture_t * depthtexture,rtexture_t * colortexture)7284 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7285 {
7286 	qboolean shadowmapping = false;
7287 
7288 	if (r_timereport_active)
7289 		R_TimeReport("beginscene");
7290 
7291 	r_refdef.stats[r_stat_renders]++;
7292 
7293 	R_UpdateFog();
7294 
7295 	// don't let sound skip if going slow
7296 	if (r_refdef.scene.extraupdate)
7297 		S_ExtraUpdate ();
7298 
7299 	R_MeshQueue_BeginScene();
7300 
7301 	R_SkyStartFrame();
7302 
7303 	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);
7304 
7305 	if (r_timereport_active)
7306 		R_TimeReport("skystartframe");
7307 
7308 	if (cl.csqc_vidvars.drawworld)
7309 	{
7310 		// don't let sound skip if going slow
7311 		if (r_refdef.scene.extraupdate)
7312 			S_ExtraUpdate ();
7313 
7314 		if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7315 		{
7316 			r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7317 			if (r_timereport_active)
7318 				R_TimeReport("worldsky");
7319 		}
7320 
7321 		if (R_DrawBrushModelsSky() && r_timereport_active)
7322 			R_TimeReport("bmodelsky");
7323 
7324 		if (skyrendermasked && skyrenderlater)
7325 		{
7326 			// we have to force off the water clipping plane while rendering sky
7327 			R_SetupView(false, fbo, depthtexture, colortexture);
7328 			R_Sky();
7329 			R_SetupView(true, fbo, depthtexture, colortexture);
7330 			if (r_timereport_active)
7331 				R_TimeReport("sky");
7332 		}
7333 	}
7334 
7335 	R_Shadow_PrepareModelShadows();
7336 	R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7337 	if (r_timereport_active)
7338 		R_TimeReport("preparelights");
7339 
7340 	// render all the shadowmaps that will be used for this view
7341 	shadowmapping = R_Shadow_ShadowMappingEnabled();
7342 	if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7343 	{
7344 		R_Shadow_DrawShadowMaps();
7345 		if (r_timereport_active)
7346 			R_TimeReport("shadowmaps");
7347 	}
7348 
7349 	// render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7350 	if (r_shadow_usingdeferredprepass)
7351 		R_Shadow_DrawPrepass();
7352 
7353 	// now we begin the forward pass of the view render
7354 	if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7355 	{
7356 		r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7357 		if (r_timereport_active)
7358 			R_TimeReport("worlddepth");
7359 	}
7360 	if (r_depthfirst.integer >= 2)
7361 	{
7362 		R_DrawModelsDepth();
7363 		if (r_timereport_active)
7364 			R_TimeReport("modeldepth");
7365 	}
7366 
7367 	if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7368 	{
7369 		r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7370 		if (r_timereport_active)
7371 			R_TimeReport("world");
7372 	}
7373 
7374 	// don't let sound skip if going slow
7375 	if (r_refdef.scene.extraupdate)
7376 		S_ExtraUpdate ();
7377 
7378 	R_DrawModels();
7379 	if (r_timereport_active)
7380 		R_TimeReport("models");
7381 
7382 	// don't let sound skip if going slow
7383 	if (r_refdef.scene.extraupdate)
7384 		S_ExtraUpdate ();
7385 
7386 	if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7387 	{
7388 		R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7389 		R_Shadow_DrawModelShadows();
7390 		R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7391 		// don't let sound skip if going slow
7392 		if (r_refdef.scene.extraupdate)
7393 			S_ExtraUpdate ();
7394 	}
7395 
7396 	if (!r_shadow_usingdeferredprepass)
7397 	{
7398 		R_Shadow_DrawLights();
7399 		if (r_timereport_active)
7400 			R_TimeReport("rtlights");
7401 	}
7402 
7403 	// don't let sound skip if going slow
7404 	if (r_refdef.scene.extraupdate)
7405 		S_ExtraUpdate ();
7406 
7407 	if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7408 	{
7409 		R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410 		R_Shadow_DrawModelShadows();
7411 		R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412 		// don't let sound skip if going slow
7413 		if (r_refdef.scene.extraupdate)
7414 			S_ExtraUpdate ();
7415 	}
7416 
7417 	if (cl.csqc_vidvars.drawworld)
7418 	{
7419 		if (cl_decals_newsystem.integer)
7420 		{
7421 			R_DrawModelDecals();
7422 			if (r_timereport_active)
7423 				R_TimeReport("modeldecals");
7424 		}
7425 		else
7426 		{
7427 			R_DrawDecals();
7428 			if (r_timereport_active)
7429 				R_TimeReport("decals");
7430 		}
7431 
7432 		R_DrawParticles();
7433 		if (r_timereport_active)
7434 			R_TimeReport("particles");
7435 
7436 		R_DrawExplosions();
7437 		if (r_timereport_active)
7438 			R_TimeReport("explosions");
7439 	}
7440 
7441 	if (cl.csqc_loaded)
7442 		VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7443 
7444 	if (r_refdef.view.showdebug)
7445 	{
7446 		if (cl_locs_show.integer)
7447 		{
7448 			R_DrawLocs();
7449 			if (r_timereport_active)
7450 				R_TimeReport("showlocs");
7451 		}
7452 
7453 		if (r_drawportals.integer)
7454 		{
7455 			R_DrawPortals();
7456 			if (r_timereport_active)
7457 				R_TimeReport("portals");
7458 		}
7459 
7460 		if (r_showbboxes_client.value > 0)
7461 		{
7462 			R_DrawEntityBBoxes(CLVM_prog);
7463 			if (r_timereport_active)
7464 				R_TimeReport("clbboxes");
7465 		}
7466 		if (r_showbboxes.value > 0)
7467 		{
7468 			R_DrawEntityBBoxes(SVVM_prog);
7469 			if (r_timereport_active)
7470 				R_TimeReport("svbboxes");
7471 		}
7472 	}
7473 
7474 	if (r_transparent.integer)
7475 	{
7476 		R_MeshQueue_RenderTransparent();
7477 		if (r_timereport_active)
7478 			R_TimeReport("drawtrans");
7479 	}
7480 
7481 	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))
7482 	{
7483 		r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7484 		if (r_timereport_active)
7485 			R_TimeReport("worlddebug");
7486 		R_DrawModelsDebug();
7487 		if (r_timereport_active)
7488 			R_TimeReport("modeldebug");
7489 	}
7490 
7491 	if (cl.csqc_vidvars.drawworld)
7492 	{
7493 		R_Shadow_DrawCoronas();
7494 		if (r_timereport_active)
7495 			R_TimeReport("coronas");
7496 	}
7497 
7498 #if 0
7499 	{
7500 		GL_DepthTest(false);
7501 		qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7502 		GL_Color(1, 1, 1, 1);
7503 		qglBegin(GL_POLYGON);
7504 		qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7505 		qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7506 		qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7507 		qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7508 		qglEnd();
7509 		qglBegin(GL_POLYGON);
7510 		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]);
7511 		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]);
7512 		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]);
7513 		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]);
7514 		qglEnd();
7515 		qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7516 	}
7517 #endif
7518 
7519 	// don't let sound skip if going slow
7520 	if (r_refdef.scene.extraupdate)
7521 		S_ExtraUpdate ();
7522 }
7523 
7524 static const unsigned short bboxelements[36] =
7525 {
7526 	5, 1, 3, 5, 3, 7,
7527 	6, 2, 0, 6, 0, 4,
7528 	7, 3, 2, 7, 2, 6,
7529 	4, 0, 1, 4, 1, 5,
7530 	4, 5, 7, 4, 7, 6,
7531 	1, 0, 2, 1, 2, 3,
7532 };
7533 
7534 #define BBOXEDGES 13
7535 static const float bboxedges[BBOXEDGES][6] =
7536 {
7537 	// whole box
7538 	{ 0, 0, 0, 1, 1, 1 },
7539 	// bottom edges
7540 	{ 0, 0, 0, 0, 1, 0 },
7541 	{ 0, 0, 0, 1, 0, 0 },
7542 	{ 0, 1, 0, 1, 1, 0 },
7543 	{ 1, 0, 0, 1, 1, 0 },
7544 	// top edges
7545 	{ 0, 0, 1, 0, 1, 1 },
7546 	{ 0, 0, 1, 1, 0, 1 },
7547 	{ 0, 1, 1, 1, 1, 1 },
7548 	{ 1, 0, 1, 1, 1, 1 },
7549 	// vertical edges
7550 	{ 0, 0, 0, 0, 0, 1 },
7551 	{ 1, 0, 0, 1, 0, 1 },
7552 	{ 0, 1, 0, 0, 1, 1 },
7553 	{ 1, 1, 0, 1, 1, 1 },
7554 };
7555 
R_DrawBBoxMesh(vec3_t mins,vec3_t maxs,float cr,float cg,float cb,float ca)7556 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7557 {
7558 	int numvertices = BBOXEDGES * 8;
7559 	float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7560 	int numtriangles = BBOXEDGES * 12;
7561 	unsigned short elements[BBOXEDGES * 36];
7562 	int i, edge;
7563 	float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7564 
7565 	RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7566 
7567 	GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7568 	GL_DepthMask(false);
7569 	GL_DepthRange(0, 1);
7570 	GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7571 
7572 	for (edge = 0; edge < BBOXEDGES; edge++)
7573 	{
7574 		for (i = 0; i < 3; i++)
7575 		{
7576 			edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7577 			edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7578 		}
7579 		vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7580 		vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7581 		vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7582 		vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7583 		vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7584 		vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7585 		vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7586 		vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7587 		for (i = 0; i < 36; i++)
7588 			elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7589 	}
7590 	R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7591 	if (r_refdef.fogenabled)
7592 	{
7593 		for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7594 		{
7595 			f1 = RSurf_FogVertex(v);
7596 			f2 = 1 - f1;
7597 			c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7598 			c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7599 			c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7600 		}
7601 	}
7602 	R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7603 	R_Mesh_ResetTextureState();
7604 	R_SetupShader_Generic_NoTexture(false, false);
7605 	R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7606 }
7607 
R_DrawEntityBBoxes_Callback(const entity_render_t * ent,const rtlight_t * rtlight,int numsurfaces,int * surfacelist)7608 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7609 {
7610 	// hacky overloading of the parameters
7611 	prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7612 	int i;
7613 	float color[4];
7614 	prvm_edict_t *edict;
7615 
7616 	GL_CullFace(GL_NONE);
7617 	R_SetupShader_Generic_NoTexture(false, false);
7618 
7619 	for (i = 0;i < numsurfaces;i++)
7620 	{
7621 		edict = PRVM_EDICT_NUM(surfacelist[i]);
7622 		switch ((int)PRVM_serveredictfloat(edict, solid))
7623 		{
7624 			case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7625 			case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7626 			case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7627 			case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7628 			case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7629 			case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7630 			default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7631 		}
7632 		if (prog == CLVM_prog)
7633 			color[3] *= r_showbboxes_client.value;
7634 		else
7635 			color[3] *= r_showbboxes.value;
7636 		color[3] = bound(0, color[3], 1);
7637 		GL_DepthTest(!r_showdisabledepthtest.integer);
7638 		R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7639 	}
7640 }
7641 
R_DrawEntityBBoxes(prvm_prog_t * prog)7642 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7643 {
7644 	int i;
7645 	prvm_edict_t *edict;
7646 	vec3_t center;
7647 
7648 	if (prog == NULL)
7649 		return;
7650 
7651 	for (i = 0; i < prog->num_edicts; i++)
7652 	{
7653 		edict = PRVM_EDICT_NUM(i);
7654 		if (edict->priv.server->free)
7655 			continue;
7656 		// exclude the following for now, as they don't live in world coordinate space and can't be solid:
7657 		if (PRVM_serveredictedict(edict, tag_entity) != 0)
7658 			continue;
7659 		if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7660 			continue;
7661 		VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7662 		R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7663 	}
7664 }
7665 
7666 static const int nomodelelement3i[24] =
7667 {
7668 	5, 2, 0,
7669 	5, 1, 2,
7670 	5, 0, 3,
7671 	5, 3, 1,
7672 	0, 2, 4,
7673 	2, 1, 4,
7674 	3, 0, 4,
7675 	1, 3, 4
7676 };
7677 
7678 static const unsigned short nomodelelement3s[24] =
7679 {
7680 	5, 2, 0,
7681 	5, 1, 2,
7682 	5, 0, 3,
7683 	5, 3, 1,
7684 	0, 2, 4,
7685 	2, 1, 4,
7686 	3, 0, 4,
7687 	1, 3, 4
7688 };
7689 
7690 static const float nomodelvertex3f[6*3] =
7691 {
7692 	-16,   0,   0,
7693 	 16,   0,   0,
7694 	  0, -16,   0,
7695 	  0,  16,   0,
7696 	  0,   0, -16,
7697 	  0,   0,  16
7698 };
7699 
7700 static const float nomodelcolor4f[6*4] =
7701 {
7702 	0.0f, 0.0f, 0.5f, 1.0f,
7703 	0.0f, 0.0f, 0.5f, 1.0f,
7704 	0.0f, 0.5f, 0.0f, 1.0f,
7705 	0.0f, 0.5f, 0.0f, 1.0f,
7706 	0.5f, 0.0f, 0.0f, 1.0f,
7707 	0.5f, 0.0f, 0.0f, 1.0f
7708 };
7709 
R_DrawNoModel_TransparentCallback(const entity_render_t * ent,const rtlight_t * rtlight,int numsurfaces,int * surfacelist)7710 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7711 {
7712 	int i;
7713 	float f1, f2, *c;
7714 	float color4f[6*4];
7715 
7716 	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);
7717 
7718 	// this is only called once per entity so numsurfaces is always 1, and
7719 	// surfacelist is always {0}, so this code does not handle batches
7720 
7721 	if (rsurface.ent_flags & RENDER_ADDITIVE)
7722 	{
7723 		GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7724 		GL_DepthMask(false);
7725 	}
7726 	else if (ent->alpha < 1)
7727 	{
7728 		GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7729 		GL_DepthMask(false);
7730 	}
7731 	else
7732 	{
7733 		GL_BlendFunc(GL_ONE, GL_ZERO);
7734 		GL_DepthMask(true);
7735 	}
7736 	GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7737 	GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7738 	GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7739 	GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7740 	memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7741 	for (i = 0, c = color4f;i < 6;i++, c += 4)
7742 	{
7743 		c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7744 		c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7745 		c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7746 		c[3] *= ent->alpha;
7747 	}
7748 	if (r_refdef.fogenabled)
7749 	{
7750 		for (i = 0, c = color4f;i < 6;i++, c += 4)
7751 		{
7752 			f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7753 			f2 = 1 - f1;
7754 			c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7755 			c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7756 			c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7757 		}
7758 	}
7759 //	R_Mesh_ResetTextureState();
7760 	R_SetupShader_Generic_NoTexture(false, false);
7761 	R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7762 	R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7763 }
7764 
R_DrawNoModel(entity_render_t * ent)7765 void R_DrawNoModel(entity_render_t *ent)
7766 {
7767 	vec3_t org;
7768 	Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7769 	if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7770 		R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7771 	else
7772 		R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7773 }
7774 
R_CalcBeam_Vertex3f(float * vert,const float * org1,const float * org2,float width)7775 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7776 {
7777 	vec3_t right1, right2, diff, normal;
7778 
7779 	VectorSubtract (org2, org1, normal);
7780 
7781 	// calculate 'right' vector for start
7782 	VectorSubtract (r_refdef.view.origin, org1, diff);
7783 	CrossProduct (normal, diff, right1);
7784 	VectorNormalize (right1);
7785 
7786 	// calculate 'right' vector for end
7787 	VectorSubtract (r_refdef.view.origin, org2, diff);
7788 	CrossProduct (normal, diff, right2);
7789 	VectorNormalize (right2);
7790 
7791 	vert[ 0] = org1[0] + width * right1[0];
7792 	vert[ 1] = org1[1] + width * right1[1];
7793 	vert[ 2] = org1[2] + width * right1[2];
7794 	vert[ 3] = org1[0] - width * right1[0];
7795 	vert[ 4] = org1[1] - width * right1[1];
7796 	vert[ 5] = org1[2] - width * right1[2];
7797 	vert[ 6] = org2[0] - width * right2[0];
7798 	vert[ 7] = org2[1] - width * right2[1];
7799 	vert[ 8] = org2[2] - width * right2[2];
7800 	vert[ 9] = org2[0] + width * right2[0];
7801 	vert[10] = org2[1] + width * right2[1];
7802 	vert[11] = org2[2] + width * right2[2];
7803 }
7804 
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)7805 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)
7806 {
7807 	vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7808 	vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7809 	vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7810 	vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7811 	vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7812 	vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7813 	vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7814 	vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7815 	vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7816 	vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7817 	vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7818 	vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7819 }
7820 
R_Mesh_AddVertex(rmesh_t * mesh,float x,float y,float z)7821 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7822 {
7823 	int i;
7824 	float *vertex3f;
7825 	float v[3];
7826 	VectorSet(v, x, y, z);
7827 	for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7828 		if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7829 			break;
7830 	if (i == mesh->numvertices)
7831 	{
7832 		if (mesh->numvertices < mesh->maxvertices)
7833 		{
7834 			VectorCopy(v, vertex3f);
7835 			mesh->numvertices++;
7836 		}
7837 		return mesh->numvertices;
7838 	}
7839 	else
7840 		return i;
7841 }
7842 
R_Mesh_AddPolygon3f(rmesh_t * mesh,int numvertices,float * vertex3f)7843 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7844 {
7845 	int i;
7846 	int *e, element[3];
7847 	element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7848 	element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7849 	e = mesh->element3i + mesh->numtriangles * 3;
7850 	for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7851 	{
7852 		element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7853 		if (mesh->numtriangles < mesh->maxtriangles)
7854 		{
7855 			*e++ = element[0];
7856 			*e++ = element[1];
7857 			*e++ = element[2];
7858 			mesh->numtriangles++;
7859 		}
7860 		element[1] = element[2];
7861 	}
7862 }
7863 
R_Mesh_AddPolygon3d(rmesh_t * mesh,int numvertices,double * vertex3d)7864 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7865 {
7866 	int i;
7867 	int *e, element[3];
7868 	element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7869 	element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7870 	e = mesh->element3i + mesh->numtriangles * 3;
7871 	for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7872 	{
7873 		element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7874 		if (mesh->numtriangles < mesh->maxtriangles)
7875 		{
7876 			*e++ = element[0];
7877 			*e++ = element[1];
7878 			*e++ = element[2];
7879 			mesh->numtriangles++;
7880 		}
7881 		element[1] = element[2];
7882 	}
7883 }
7884 
7885 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
R_Mesh_AddBrushMeshFromPlanes(rmesh_t * mesh,int numplanes,mplane_t * planes)7886 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7887 {
7888 	int planenum, planenum2;
7889 	int w;
7890 	int tempnumpoints;
7891 	mplane_t *plane, *plane2;
7892 	double maxdist;
7893 	double temppoints[2][256*3];
7894 	// figure out how large a bounding box we need to properly compute this brush
7895 	maxdist = 0;
7896 	for (w = 0;w < numplanes;w++)
7897 		maxdist = max(maxdist, fabs(planes[w].dist));
7898 	// now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7899 	maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7900 	for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7901 	{
7902 		w = 0;
7903 		tempnumpoints = 4;
7904 		PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7905 		for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7906 		{
7907 			if (planenum2 == planenum)
7908 				continue;
7909 			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);
7910 			w = !w;
7911 		}
7912 		if (tempnumpoints < 3)
7913 			continue;
7914 		// generate elements forming a triangle fan for this polygon
7915 		R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7916 	}
7917 }
7918 
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)7919 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)
7920 {
7921 	texturelayer_t *layer;
7922 	layer = t->currentlayers + t->currentnumlayers++;
7923 	layer->type = type;
7924 	layer->depthmask = depthmask;
7925 	layer->blendfunc1 = blendfunc1;
7926 	layer->blendfunc2 = blendfunc2;
7927 	layer->texture = texture;
7928 	layer->texmatrix = *matrix;
7929 	layer->color[0] = r;
7930 	layer->color[1] = g;
7931 	layer->color[2] = b;
7932 	layer->color[3] = a;
7933 }
7934 
R_TestQ3WaveFunc(q3wavefunc_t func,const float * parms)7935 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7936 {
7937 	if(parms[0] == 0 && parms[1] == 0)
7938 		return false;
7939 	if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7940 		if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7941 			return false;
7942 	return true;
7943 }
7944 
R_EvaluateQ3WaveFunc(q3wavefunc_t func,const float * parms)7945 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7946 {
7947 	double index, f;
7948 	index = parms[2] + rsurface.shadertime * parms[3];
7949 	index -= floor(index);
7950 	switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7951 	{
7952 	default:
7953 	case Q3WAVEFUNC_NONE:
7954 	case Q3WAVEFUNC_NOISE:
7955 	case Q3WAVEFUNC_COUNT:
7956 		f = 0;
7957 		break;
7958 	case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7959 	case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7960 	case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7961 	case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7962 	case Q3WAVEFUNC_TRIANGLE:
7963 		index *= 4;
7964 		f = index - floor(index);
7965 		if (index < 1)
7966 		{
7967 			// f = f;
7968 		}
7969 		else if (index < 2)
7970 			f = 1 - f;
7971 		else if (index < 3)
7972 			f = -f;
7973 		else
7974 			f = -(1 - f);
7975 		break;
7976 	}
7977 	f = parms[0] + parms[1] * f;
7978 	if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7979 		f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7980 	return (float) f;
7981 }
7982 
R_tcMod_ApplyToMatrix(matrix4x4_t * texmatrix,q3shaderinfo_layer_tcmod_t * tcmod,int currentmaterialflags)7983 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7984 {
7985 	int w, h, idx;
7986 	float shadertime;
7987 	float f;
7988 	float offsetd[2];
7989 	float tcmat[12];
7990 	matrix4x4_t matrix, temp;
7991 	// if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7992 	// it's better to have one huge fixup every 9 hours than gradual
7993 	// degradation over time which looks consistently bad after many hours.
7994 	//
7995 	// tcmod scroll in particular suffers from this degradation which can't be
7996 	// effectively worked around even with floor() tricks because we don't
7997 	// know if tcmod scroll is the last tcmod being applied, and for clampmap
7998 	// a workaround involving floor() would be incorrect anyway...
7999 	shadertime = rsurface.shadertime;
8000 	if (shadertime >= 32768.0f)
8001 		shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8002 	switch(tcmod->tcmod)
8003 	{
8004 		case Q3TCMOD_COUNT:
8005 		case Q3TCMOD_NONE:
8006 			if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8007 				matrix = r_waterscrollmatrix;
8008 			else
8009 				matrix = identitymatrix;
8010 			break;
8011 		case Q3TCMOD_ENTITYTRANSLATE:
8012 			// this is used in Q3 to allow the gamecode to control texcoord
8013 			// scrolling on the entity, which is not supported in darkplaces yet.
8014 			Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8015 			break;
8016 		case Q3TCMOD_ROTATE:
8017 			Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8018 			Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8019 			Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8020 			break;
8021 		case Q3TCMOD_SCALE:
8022 			Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8023 			break;
8024 		case Q3TCMOD_SCROLL:
8025 			// this particular tcmod is a "bug for bug" compatible one with regards to
8026 			// Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8027 			// specifically did the wrapping and so we must mimic that...
8028 			offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8029 			offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8030 			Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8031 			break;
8032 		case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8033 			w = (int) tcmod->parms[0];
8034 			h = (int) tcmod->parms[1];
8035 			f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8036 			f = f - floor(f);
8037 			idx = (int) floor(f * w * h);
8038 			Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8039 			break;
8040 		case Q3TCMOD_STRETCH:
8041 			f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8042 			Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8043 			break;
8044 		case Q3TCMOD_TRANSFORM:
8045 			VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8046 			VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8047 			VectorSet(tcmat +  6, 0                   , 0                , 1);
8048 			VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8049 			Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8050 			break;
8051 		case Q3TCMOD_TURBULENT:
8052 			// this is handled in the RSurf_PrepareVertices function
8053 			matrix = identitymatrix;
8054 			break;
8055 	}
8056 	temp = *texmatrix;
8057 	Matrix4x4_Concat(texmatrix, &matrix, &temp);
8058 }
8059 
R_LoadQWSkin(r_qwskincache_t * cache,const char * skinname)8060 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8061 {
8062 	int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8063 	char name[MAX_QPATH];
8064 	skinframe_t *skinframe;
8065 	unsigned char pixels[296*194];
8066 	strlcpy(cache->name, skinname, sizeof(cache->name));
8067 	dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8068 	if (developer_loading.integer)
8069 		Con_Printf("loading %s\n", name);
8070 	skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8071 	if (!skinframe || !skinframe->base)
8072 	{
8073 		unsigned char *f;
8074 		fs_offset_t filesize;
8075 		skinframe = NULL;
8076 		f = FS_LoadFile(name, tempmempool, true, &filesize);
8077 		if (f)
8078 		{
8079 			if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8080 				skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8081 			Mem_Free(f);
8082 		}
8083 	}
8084 	cache->skinframe = skinframe;
8085 }
8086 
R_GetCurrentTexture(texture_t * t)8087 texture_t *R_GetCurrentTexture(texture_t *t)
8088 {
8089 	int i, q;
8090 	const entity_render_t *ent = rsurface.entity;
8091 	dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8092 	q3shaderinfo_layer_tcmod_t *tcmod;
8093 	float specularscale = 0.0f;
8094 
8095 	if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8096 		return t->currentframe;
8097 	t->update_lastrenderframe = r_textureframe;
8098 	t->update_lastrenderentity = (void *)ent;
8099 
8100 	if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8101 		t->camera_entity = ent->entitynumber;
8102 	else
8103 		t->camera_entity = 0;
8104 
8105 	// switch to an alternate material if this is a q1bsp animated material
8106 	{
8107 		texture_t *texture = t;
8108 		int s = rsurface.ent_skinnum;
8109 		if ((unsigned int)s >= (unsigned int)model->numskins)
8110 			s = 0;
8111 		if (model->skinscenes)
8112 		{
8113 			if (model->skinscenes[s].framecount > 1)
8114 				s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8115 			else
8116 				s = model->skinscenes[s].firstframe;
8117 		}
8118 		if (s > 0)
8119 			t = t + s * model->num_surfaces;
8120 		if (t->animated)
8121 		{
8122 			// use an alternate animation if the entity's frame is not 0,
8123 			// and only if the texture has an alternate animation
8124 			if (t->animated == 2) // q2bsp
8125 				t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8126 			else if (rsurface.ent_alttextures && t->anim_total[1])
8127 				t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8128 			else
8129 				t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8130 		}
8131 		texture->currentframe = t;
8132 	}
8133 
8134 	// update currentskinframe to be a qw skin or animation frame
8135 	if (rsurface.ent_qwskin >= 0)
8136 	{
8137 		i = rsurface.ent_qwskin;
8138 		if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8139 		{
8140 			r_qwskincache_size = cl.maxclients;
8141 			if (r_qwskincache)
8142 				Mem_Free(r_qwskincache);
8143 			r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8144 		}
8145 		if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8146 			R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8147 		t->currentskinframe = r_qwskincache[i].skinframe;
8148 		if (t->materialshaderpass && t->currentskinframe == NULL)
8149 			t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8150 	}
8151 	else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8152 		t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8153 	if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8154 		t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8155 
8156 	t->currentmaterialflags = t->basematerialflags;
8157 	t->currentalpha = rsurface.entity->alpha * t->basealpha;
8158 	if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8159 		t->currentalpha *= r_wateralpha.value;
8160 	if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8161 		t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8162 	if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8163 		t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8164 
8165 	// decide on which type of lighting to use for this surface
8166 	if (rsurface.entity->render_modellight_forced)
8167 		t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8168 	if (rsurface.entity->render_rtlight_disabled)
8169 		t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8170 	if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8171 	{
8172 		// some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8173 		t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8174 		for (q = 0; q < 3; q++)
8175 		{
8176 			t->render_glowmod[q] = rsurface.entity->glowmod[q];
8177 			t->render_modellight_lightdir[q] = q == 2;
8178 			t->render_modellight_ambient[q] = 1;
8179 			t->render_modellight_diffuse[q] = 0;
8180 			t->render_modellight_specular[q] = 0;
8181 			t->render_lightmap_ambient[q] = 0;
8182 			t->render_lightmap_diffuse[q] = 0;
8183 			t->render_lightmap_specular[q] = 0;
8184 			t->render_rtlight_diffuse[q] = 0;
8185 			t->render_rtlight_specular[q] = 0;
8186 		}
8187 	}
8188 	else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8189 	{
8190 		// fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8191 		t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8192 		for (q = 0; q < 3; q++)
8193 		{
8194 			t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8195 			t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8196 			t->render_modellight_lightdir[q] = q == 2;
8197 			t->render_modellight_diffuse[q] = 0;
8198 			t->render_modellight_specular[q] = 0;
8199 			t->render_lightmap_ambient[q] = 0;
8200 			t->render_lightmap_diffuse[q] = 0;
8201 			t->render_lightmap_specular[q] = 0;
8202 			t->render_rtlight_diffuse[q] = 0;
8203 			t->render_rtlight_specular[q] = 0;
8204 		}
8205 	}
8206 	else if (FAKELIGHT_ENABLED)
8207 	{
8208 		// no modellight if using fakelight for the map
8209 		t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8210 		for (q = 0; q < 3; q++)
8211 		{
8212 			t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8213 			t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8214 			t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8215 			t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8216 			t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8217 			t->render_lightmap_ambient[q] = 0;
8218 			t->render_lightmap_diffuse[q] = 0;
8219 			t->render_lightmap_specular[q] = 0;
8220 			t->render_rtlight_diffuse[q] = 0;
8221 			t->render_rtlight_specular[q] = 0;
8222 		}
8223 	}
8224 	else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8225 	{
8226 		// ambient + single direction light (modellight)
8227 		t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8228 		for (q = 0; q < 3; q++)
8229 		{
8230 			t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8231 			t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8232 			t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8233 			t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8234 			t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8235 			t->render_lightmap_ambient[q] = 0;
8236 			t->render_lightmap_diffuse[q] = 0;
8237 			t->render_lightmap_specular[q] = 0;
8238 			t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8239 			t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8240 		}
8241 	}
8242 	else
8243 	{
8244 		// lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8245 		for (q = 0; q < 3; q++)
8246 		{
8247 			t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8248 			t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8249 			t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8250 			t->render_modellight_diffuse[q] = 0;
8251 			t->render_modellight_specular[q] = 0;
8252 			t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8253 			t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8254 			t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8255 			t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8256 			t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8257 		}
8258 	}
8259 
8260 	for (q = 0; q < 3; q++)
8261 	{
8262 		t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8263 		t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8264 	}
8265 
8266 	if (rsurface.ent_flags & RENDER_ADDITIVE)
8267 		t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8268 	else if (t->currentalpha < 1)
8269 		t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8270 	// LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8271 	if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8272 		t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8273 	if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8274 		t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8275 	if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8276 		t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8277 	if (t->backgroundshaderpass)
8278 		t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8279 	if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8280 	{
8281 		if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8282 			t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8283 	}
8284 	else
8285 		t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8286 	if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8287 	{
8288 		// promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8289 		t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8290 	}
8291 	if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8292 		t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8293 
8294 	// there is no tcmod
8295 	if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8296 	{
8297 		t->currenttexmatrix = r_waterscrollmatrix;
8298 		t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8299 	}
8300 	else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8301 	{
8302 		Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8303 		Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8304 	}
8305 
8306 	if (t->materialshaderpass)
8307 		for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8308 			R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8309 
8310 	t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8311 	if (t->currentskinframe->qpixels)
8312 		R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8313 	t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8314 	if (!t->basetexture)
8315 		t->basetexture = r_texture_notexture;
8316 	t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8317 	t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8318 	t->nmaptexture = t->currentskinframe->nmap;
8319 	if (!t->nmaptexture)
8320 		t->nmaptexture = r_texture_blanknormalmap;
8321 	t->glosstexture = r_texture_black;
8322 	t->glowtexture = t->currentskinframe->glow;
8323 	t->fogtexture = t->currentskinframe->fog;
8324 	t->reflectmasktexture = t->currentskinframe->reflect;
8325 	if (t->backgroundshaderpass)
8326 	{
8327 		for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8328 			R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8329 		t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8330 		t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8331 		t->backgroundglosstexture = r_texture_black;
8332 		t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8333 		if (!t->backgroundnmaptexture)
8334 			t->backgroundnmaptexture = r_texture_blanknormalmap;
8335 		// make sure that if glow is going to be used, both textures are not NULL
8336 		if (!t->backgroundglowtexture && t->glowtexture)
8337 			t->backgroundglowtexture = r_texture_black;
8338 		if (!t->glowtexture && t->backgroundglowtexture)
8339 			t->glowtexture = r_texture_black;
8340 	}
8341 	else
8342 	{
8343 		t->backgroundbasetexture = r_texture_white;
8344 		t->backgroundnmaptexture = r_texture_blanknormalmap;
8345 		t->backgroundglosstexture = r_texture_black;
8346 		t->backgroundglowtexture = NULL;
8347 	}
8348 	t->specularpower = r_shadow_glossexponent.value;
8349 	// TODO: store reference values for these in the texture?
8350 	if (r_shadow_gloss.integer > 0)
8351 	{
8352 		if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8353 		{
8354 			if (r_shadow_glossintensity.value > 0)
8355 			{
8356 				t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8357 				t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8358 				specularscale = r_shadow_glossintensity.value;
8359 			}
8360 		}
8361 		else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8362 		{
8363 			t->glosstexture = r_texture_white;
8364 			t->backgroundglosstexture = r_texture_white;
8365 			specularscale = r_shadow_gloss2intensity.value;
8366 			t->specularpower = r_shadow_gloss2exponent.value;
8367 		}
8368 	}
8369 	specularscale *= t->specularscalemod;
8370 	t->specularpower *= t->specularpowermod;
8371 
8372 	// lightmaps mode looks bad with dlights using actual texturing, so turn
8373 	// off the colormap and glossmap, but leave the normalmap on as it still
8374 	// accurately represents the shading involved
8375 	if (gl_lightmaps.integer)
8376 	{
8377 		t->basetexture = r_texture_grey128;
8378 		t->pantstexture = r_texture_black;
8379 		t->shirttexture = r_texture_black;
8380 		if (gl_lightmaps.integer < 2)
8381 			t->nmaptexture = r_texture_blanknormalmap;
8382 		t->glosstexture = r_texture_black;
8383 		t->glowtexture = NULL;
8384 		t->fogtexture = NULL;
8385 		t->reflectmasktexture = NULL;
8386 		t->backgroundbasetexture = NULL;
8387 		if (gl_lightmaps.integer < 2)
8388 			t->backgroundnmaptexture = r_texture_blanknormalmap;
8389 		t->backgroundglosstexture = r_texture_black;
8390 		t->backgroundglowtexture = NULL;
8391 		specularscale = 0;
8392 		t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8393 	}
8394 
8395 	if (specularscale != 1.0f)
8396 	{
8397 		for (q = 0; q < 3; q++)
8398 		{
8399 			t->render_modellight_specular[q] *= specularscale;
8400 			t->render_lightmap_specular[q] *= specularscale;
8401 			t->render_rtlight_specular[q] *= specularscale;
8402 		}
8403 	}
8404 
8405 	t->currentnumlayers = 0;
8406 	if (t->currentmaterialflags & MATERIALFLAG_WALL)
8407 	{
8408 		int blendfunc1, blendfunc2;
8409 		qboolean depthmask;
8410 		if (t->currentmaterialflags & MATERIALFLAG_ADD)
8411 		{
8412 			blendfunc1 = GL_SRC_ALPHA;
8413 			blendfunc2 = GL_ONE;
8414 		}
8415 		else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8416 		{
8417 			blendfunc1 = GL_SRC_ALPHA;
8418 			blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8419 		}
8420 		else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8421 		{
8422 			blendfunc1 = t->customblendfunc[0];
8423 			blendfunc2 = t->customblendfunc[1];
8424 		}
8425 		else
8426 		{
8427 			blendfunc1 = GL_ONE;
8428 			blendfunc2 = GL_ZERO;
8429 		}
8430 		depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8431 		if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8432 		{
8433 			// basic lit geometry
8434 			R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8435 			// add pants/shirt if needed
8436 			if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8437 				R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8438 			if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8439 				R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8440 		}
8441 		else
8442 		{
8443 			// basic lit geometry
8444 			R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8445 			// add pants/shirt if needed
8446 			if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8447 				R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8448 			if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8449 				R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8450 			// now add ambient passes if needed
8451 			if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8452 			{
8453 				R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8454 				if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8455 					R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8456 				if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8457 					R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8458 			}
8459 		}
8460 		if (t->glowtexture != NULL && !gl_lightmaps.integer)
8461 			R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8462 		if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8463 		{
8464 			// if this is opaque use alpha blend which will darken the earlier
8465 			// passes cheaply.
8466 			//
8467 			// if this is an alpha blended material, all the earlier passes
8468 			// were darkened by fog already, so we only need to add the fog
8469 			// color ontop through the fog mask texture
8470 			//
8471 			// if this is an additive blended material, all the earlier passes
8472 			// were darkened by fog already, and we should not add fog color
8473 			// (because the background was not darkened, there is no fog color
8474 			// that was lost behind it).
8475 			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->currentalpha);
8476 		}
8477 	}
8478 
8479 	return t;
8480 }
8481 
8482 rsurfacestate_t rsurface;
8483 
RSurf_ActiveModelEntity(const entity_render_t * ent,qboolean wantnormals,qboolean wanttangents,qboolean prepass)8484 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8485 {
8486 	dp_model_t *model = ent->model;
8487 	//if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8488 	//	return;
8489 	rsurface.entity = (entity_render_t *)ent;
8490 	rsurface.skeleton = ent->skeleton;
8491 	memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8492 	rsurface.ent_skinnum = ent->skinnum;
8493 	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;
8494 	rsurface.ent_flags = ent->flags;
8495 	if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8496 		rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8497 	rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8498 	rsurface.matrix = ent->matrix;
8499 	rsurface.inversematrix = ent->inversematrix;
8500 	rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8501 	rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8502 	R_EntityMatrix(&rsurface.matrix);
8503 	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8504 	Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8505 	rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8506 	rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8507 	rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8508 	rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8509 	memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8510 	rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8511 	rsurface.basepolygonfactor = r_refdef.polygonfactor;
8512 	rsurface.basepolygonoffset = r_refdef.polygonoffset;
8513 	if (ent->model->brush.submodel && !prepass)
8514 	{
8515 		rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8516 		rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8517 	}
8518 	// if the animcache code decided it should use the shader path, skip the deform step
8519 	rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8520 	rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8521 	rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8522 	rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8523 	rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8524 	if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8525 	{
8526 		if (ent->animcache_vertex3f)
8527 		{
8528 			r_refdef.stats[r_stat_batch_entitycache_count]++;
8529 			r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8530 			r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8531 			r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8532 			rsurface.modelvertex3f = ent->animcache_vertex3f;
8533 			rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8534 			rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8535 			rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8536 			rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8537 			rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8538 			rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8539 			rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8540 			rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8541 			rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8542 			rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8543 			rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8544 			rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8545 			rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8546 			rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8547 		}
8548 		else if (wanttangents)
8549 		{
8550 			r_refdef.stats[r_stat_batch_entityanimate_count]++;
8551 			r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8552 			r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8553 			r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8554 			rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8555 			rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8556 			rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8557 			rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8558 			model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8559 			rsurface.modelvertexmesh = NULL;
8560 			rsurface.modelvertexmesh_vertexbuffer = NULL;
8561 			rsurface.modelvertexmesh_bufferoffset = 0;
8562 			rsurface.modelvertex3f_vertexbuffer = NULL;
8563 			rsurface.modelvertex3f_bufferoffset = 0;
8564 			rsurface.modelvertex3f_vertexbuffer = 0;
8565 			rsurface.modelvertex3f_bufferoffset = 0;
8566 			rsurface.modelsvector3f_vertexbuffer = 0;
8567 			rsurface.modelsvector3f_bufferoffset = 0;
8568 			rsurface.modeltvector3f_vertexbuffer = 0;
8569 			rsurface.modeltvector3f_bufferoffset = 0;
8570 			rsurface.modelnormal3f_vertexbuffer = 0;
8571 			rsurface.modelnormal3f_bufferoffset = 0;
8572 		}
8573 		else if (wantnormals)
8574 		{
8575 			r_refdef.stats[r_stat_batch_entityanimate_count]++;
8576 			r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8577 			r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8578 			r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8579 			rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8580 			rsurface.modelsvector3f = NULL;
8581 			rsurface.modeltvector3f = NULL;
8582 			rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8583 			model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8584 			rsurface.modelvertexmesh = NULL;
8585 			rsurface.modelvertexmesh_vertexbuffer = NULL;
8586 			rsurface.modelvertexmesh_bufferoffset = 0;
8587 			rsurface.modelvertex3f_vertexbuffer = NULL;
8588 			rsurface.modelvertex3f_bufferoffset = 0;
8589 			rsurface.modelvertex3f_vertexbuffer = 0;
8590 			rsurface.modelvertex3f_bufferoffset = 0;
8591 			rsurface.modelsvector3f_vertexbuffer = 0;
8592 			rsurface.modelsvector3f_bufferoffset = 0;
8593 			rsurface.modeltvector3f_vertexbuffer = 0;
8594 			rsurface.modeltvector3f_bufferoffset = 0;
8595 			rsurface.modelnormal3f_vertexbuffer = 0;
8596 			rsurface.modelnormal3f_bufferoffset = 0;
8597 		}
8598 		else
8599 		{
8600 			r_refdef.stats[r_stat_batch_entityanimate_count]++;
8601 			r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8602 			r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8603 			r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8604 			rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8605 			rsurface.modelsvector3f = NULL;
8606 			rsurface.modeltvector3f = NULL;
8607 			rsurface.modelnormal3f = NULL;
8608 			model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8609 			rsurface.modelvertexmesh = NULL;
8610 			rsurface.modelvertexmesh_vertexbuffer = NULL;
8611 			rsurface.modelvertexmesh_bufferoffset = 0;
8612 			rsurface.modelvertex3f_vertexbuffer = NULL;
8613 			rsurface.modelvertex3f_bufferoffset = 0;
8614 			rsurface.modelvertex3f_vertexbuffer = 0;
8615 			rsurface.modelvertex3f_bufferoffset = 0;
8616 			rsurface.modelsvector3f_vertexbuffer = 0;
8617 			rsurface.modelsvector3f_bufferoffset = 0;
8618 			rsurface.modeltvector3f_vertexbuffer = 0;
8619 			rsurface.modeltvector3f_bufferoffset = 0;
8620 			rsurface.modelnormal3f_vertexbuffer = 0;
8621 			rsurface.modelnormal3f_bufferoffset = 0;
8622 		}
8623 		rsurface.modelgeneratedvertex = true;
8624 	}
8625 	else
8626 	{
8627 		if (rsurface.entityskeletaltransform3x4)
8628 		{
8629 			r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8630 			r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8631 			r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8632 			r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8633 		}
8634 		else
8635 		{
8636 			r_refdef.stats[r_stat_batch_entitystatic_count]++;
8637 			r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8638 			r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8639 			r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8640 		}
8641 		rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8642 		rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643 		rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8644 		rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8645 		rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646 		rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8647 		rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8648 		rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8649 		rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8650 		rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8651 		rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8652 		rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8653 		rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8654 		rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8655 		rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8656 		rsurface.modelgeneratedvertex = false;
8657 	}
8658 	rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8659 	rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8660 	rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8661 	rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8662 	rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8663 	rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8664 	rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8665 	rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8666 	rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8667 	rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8668 	rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8669 	rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8670 	rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8671 	rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8672 	rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8673 	rsurface.modelelement3i = model->surfmesh.data_element3i;
8674 	rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8675 	rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8676 	rsurface.modelelement3s = model->surfmesh.data_element3s;
8677 	rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8678 	rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8679 	rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8680 	rsurface.modelnumvertices = model->surfmesh.num_vertices;
8681 	rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8682 	rsurface.modelsurfaces = model->data_surfaces;
8683 	rsurface.batchgeneratedvertex = false;
8684 	rsurface.batchfirstvertex = 0;
8685 	rsurface.batchnumvertices = 0;
8686 	rsurface.batchfirsttriangle = 0;
8687 	rsurface.batchnumtriangles = 0;
8688 	rsurface.batchvertex3f  = NULL;
8689 	rsurface.batchvertex3f_vertexbuffer = NULL;
8690 	rsurface.batchvertex3f_bufferoffset = 0;
8691 	rsurface.batchsvector3f = NULL;
8692 	rsurface.batchsvector3f_vertexbuffer = NULL;
8693 	rsurface.batchsvector3f_bufferoffset = 0;
8694 	rsurface.batchtvector3f = NULL;
8695 	rsurface.batchtvector3f_vertexbuffer = NULL;
8696 	rsurface.batchtvector3f_bufferoffset = 0;
8697 	rsurface.batchnormal3f  = NULL;
8698 	rsurface.batchnormal3f_vertexbuffer = NULL;
8699 	rsurface.batchnormal3f_bufferoffset = 0;
8700 	rsurface.batchlightmapcolor4f = NULL;
8701 	rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8702 	rsurface.batchlightmapcolor4f_bufferoffset = 0;
8703 	rsurface.batchtexcoordtexture2f = NULL;
8704 	rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8705 	rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8706 	rsurface.batchtexcoordlightmap2f = NULL;
8707 	rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8708 	rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8709 	rsurface.batchskeletalindex4ub = NULL;
8710 	rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8711 	rsurface.batchskeletalindex4ub_bufferoffset = 0;
8712 	rsurface.batchskeletalweight4ub = NULL;
8713 	rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8714 	rsurface.batchskeletalweight4ub_bufferoffset = 0;
8715 	rsurface.batchvertexmesh = NULL;
8716 	rsurface.batchvertexmesh_vertexbuffer = NULL;
8717 	rsurface.batchvertexmesh_bufferoffset = 0;
8718 	rsurface.batchelement3i = NULL;
8719 	rsurface.batchelement3i_indexbuffer = NULL;
8720 	rsurface.batchelement3i_bufferoffset = 0;
8721 	rsurface.batchelement3s = NULL;
8722 	rsurface.batchelement3s_indexbuffer = NULL;
8723 	rsurface.batchelement3s_bufferoffset = 0;
8724 	rsurface.passcolor4f = NULL;
8725 	rsurface.passcolor4f_vertexbuffer = NULL;
8726 	rsurface.passcolor4f_bufferoffset = 0;
8727 	rsurface.forcecurrenttextureupdate = false;
8728 }
8729 
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)8730 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)
8731 {
8732 	rsurface.entity = r_refdef.scene.worldentity;
8733 	rsurface.skeleton = NULL;
8734 	rsurface.ent_skinnum = 0;
8735 	rsurface.ent_qwskin = -1;
8736 	rsurface.ent_flags = entflags;
8737 	rsurface.shadertime = r_refdef.scene.time - shadertime;
8738 	rsurface.modelnumvertices = numvertices;
8739 	rsurface.modelnumtriangles = numtriangles;
8740 	rsurface.matrix = *matrix;
8741 	rsurface.inversematrix = *inversematrix;
8742 	rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8743 	rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8744 	R_EntityMatrix(&rsurface.matrix);
8745 	Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8746 	Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8747 	rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8748 	rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8749 	rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8750 	rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8751 	memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8752 	rsurface.frameblend[0].lerp = 1;
8753 	rsurface.ent_alttextures = false;
8754 	rsurface.basepolygonfactor = r_refdef.polygonfactor;
8755 	rsurface.basepolygonoffset = r_refdef.polygonoffset;
8756 	rsurface.entityskeletaltransform3x4 = NULL;
8757 	rsurface.entityskeletaltransform3x4buffer = NULL;
8758 	rsurface.entityskeletaltransform3x4offset = 0;
8759 	rsurface.entityskeletaltransform3x4size = 0;
8760 	rsurface.entityskeletalnumtransforms = 0;
8761 	r_refdef.stats[r_stat_batch_entitycustom_count]++;
8762 	r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8763 	r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8764 	r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8765 	if (wanttangents)
8766 	{
8767 		rsurface.modelvertex3f = (float *)vertex3f;
8768 		rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8769 		rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8770 		rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8771 	}
8772 	else if (wantnormals)
8773 	{
8774 		rsurface.modelvertex3f = (float *)vertex3f;
8775 		rsurface.modelsvector3f = NULL;
8776 		rsurface.modeltvector3f = NULL;
8777 		rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8778 	}
8779 	else
8780 	{
8781 		rsurface.modelvertex3f = (float *)vertex3f;
8782 		rsurface.modelsvector3f = NULL;
8783 		rsurface.modeltvector3f = NULL;
8784 		rsurface.modelnormal3f = NULL;
8785 	}
8786 	rsurface.modelvertexmesh = NULL;
8787 	rsurface.modelvertexmesh_vertexbuffer = NULL;
8788 	rsurface.modelvertexmesh_bufferoffset = 0;
8789 	rsurface.modelvertex3f_vertexbuffer = 0;
8790 	rsurface.modelvertex3f_bufferoffset = 0;
8791 	rsurface.modelsvector3f_vertexbuffer = 0;
8792 	rsurface.modelsvector3f_bufferoffset = 0;
8793 	rsurface.modeltvector3f_vertexbuffer = 0;
8794 	rsurface.modeltvector3f_bufferoffset = 0;
8795 	rsurface.modelnormal3f_vertexbuffer = 0;
8796 	rsurface.modelnormal3f_bufferoffset = 0;
8797 	rsurface.modelgeneratedvertex = true;
8798 	rsurface.modellightmapcolor4f  = (float *)color4f;
8799 	rsurface.modellightmapcolor4f_vertexbuffer = 0;
8800 	rsurface.modellightmapcolor4f_bufferoffset = 0;
8801 	rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8802 	rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8803 	rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8804 	rsurface.modeltexcoordlightmap2f  = NULL;
8805 	rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8806 	rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8807 	rsurface.modelskeletalindex4ub = NULL;
8808 	rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8809 	rsurface.modelskeletalindex4ub_bufferoffset = 0;
8810 	rsurface.modelskeletalweight4ub = NULL;
8811 	rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8812 	rsurface.modelskeletalweight4ub_bufferoffset = 0;
8813 	rsurface.modelelement3i = (int *)element3i;
8814 	rsurface.modelelement3i_indexbuffer = NULL;
8815 	rsurface.modelelement3i_bufferoffset = 0;
8816 	rsurface.modelelement3s = (unsigned short *)element3s;
8817 	rsurface.modelelement3s_indexbuffer = NULL;
8818 	rsurface.modelelement3s_bufferoffset = 0;
8819 	rsurface.modellightmapoffsets = NULL;
8820 	rsurface.modelsurfaces = NULL;
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 = true;
8866 
8867 	if (rsurface.modelnumvertices && rsurface.modelelement3i)
8868 	{
8869 		if ((wantnormals || wanttangents) && !normal3f)
8870 		{
8871 			rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8872 			Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8873 		}
8874 		if (wanttangents && !svector3f)
8875 		{
8876 			rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8877 			rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8878 			Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8879 		}
8880 	}
8881 }
8882 
RSurf_FogPoint(const float * v)8883 float RSurf_FogPoint(const float *v)
8884 {
8885 	// this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8886 	float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8887 	float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8888 	float FogHeightFade = r_refdef.fogheightfade;
8889 	float fogfrac;
8890 	unsigned int fogmasktableindex;
8891 	if (r_refdef.fogplaneviewabove)
8892 		fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8893 	else
8894 		fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8895 	fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8896 	return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8897 }
8898 
RSurf_FogVertex(const float * v)8899 float RSurf_FogVertex(const float *v)
8900 {
8901 	// this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8902 	float FogPlaneViewDist = rsurface.fogplaneviewdist;
8903 	float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8904 	float FogHeightFade = rsurface.fogheightfade;
8905 	float fogfrac;
8906 	unsigned int fogmasktableindex;
8907 	if (r_refdef.fogplaneviewabove)
8908 		fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8909 	else
8910 		fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8911 	fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8912 	return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8913 }
8914 
RSurf_RenumberElements(const int * inelement3i,int * outelement3i,int numelements,int adjust)8915 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8916 {
8917 	int i;
8918 	for (i = 0;i < numelements;i++)
8919 		outelement3i[i] = inelement3i[i] + adjust;
8920 }
8921 
8922 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8923 extern cvar_t gl_vbo;
RSurf_PrepareVerticesForBatch(int batchneed,int texturenumsurfaces,const msurface_t ** texturesurfacelist)8924 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8925 {
8926 	int deformindex;
8927 	int firsttriangle;
8928 	int numtriangles;
8929 	int firstvertex;
8930 	int endvertex;
8931 	int numvertices;
8932 	int surfacefirsttriangle;
8933 	int surfacenumtriangles;
8934 	int surfacefirstvertex;
8935 	int surfaceendvertex;
8936 	int surfacenumvertices;
8937 	int batchnumsurfaces = texturenumsurfaces;
8938 	int batchnumvertices;
8939 	int batchnumtriangles;
8940 	int needsupdate;
8941 	int i, j;
8942 	qboolean gaps;
8943 	qboolean dynamicvertex;
8944 	float amplitude;
8945 	float animpos;
8946 	float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8947 	float waveparms[4];
8948 	unsigned char *ub;
8949 	q3shaderinfo_deform_t *deform;
8950 	const msurface_t *surface, *firstsurface;
8951 	r_vertexmesh_t *vertexmesh;
8952 	if (!texturenumsurfaces)
8953 		return;
8954 	// find vertex range of this surface batch
8955 	gaps = false;
8956 	firstsurface = texturesurfacelist[0];
8957 	firsttriangle = firstsurface->num_firsttriangle;
8958 	batchnumvertices = 0;
8959 	batchnumtriangles = 0;
8960 	firstvertex = endvertex = firstsurface->num_firstvertex;
8961 	for (i = 0;i < texturenumsurfaces;i++)
8962 	{
8963 		surface = texturesurfacelist[i];
8964 		if (surface != firstsurface + i)
8965 			gaps = true;
8966 		surfacefirstvertex = surface->num_firstvertex;
8967 		surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8968 		surfacenumvertices = surface->num_vertices;
8969 		surfacenumtriangles = surface->num_triangles;
8970 		if (firstvertex > surfacefirstvertex)
8971 			firstvertex = surfacefirstvertex;
8972 		if (endvertex < surfaceendvertex)
8973 			endvertex = surfaceendvertex;
8974 		batchnumvertices += surfacenumvertices;
8975 		batchnumtriangles += surfacenumtriangles;
8976 	}
8977 
8978 	r_refdef.stats[r_stat_batch_batches]++;
8979 	if (gaps)
8980 		r_refdef.stats[r_stat_batch_withgaps]++;
8981 	r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8982 	r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8983 	r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8984 
8985 	// we now know the vertex range used, and if there are any gaps in it
8986 	rsurface.batchfirstvertex = firstvertex;
8987 	rsurface.batchnumvertices = endvertex - firstvertex;
8988 	rsurface.batchfirsttriangle = firsttriangle;
8989 	rsurface.batchnumtriangles = batchnumtriangles;
8990 
8991 	// this variable holds flags for which properties have been updated that
8992 	// may require regenerating vertexmesh array...
8993 	needsupdate = 0;
8994 
8995 	// check if any dynamic vertex processing must occur
8996 	dynamicvertex = false;
8997 
8998 	// a cvar to force the dynamic vertex path to be taken, for debugging
8999 	if (r_batch_debugdynamicvertexpath.integer)
9000 	{
9001 		if (!dynamicvertex)
9002 		{
9003 			r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9004 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9005 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9006 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9007 		}
9008 		dynamicvertex = true;
9009 	}
9010 
9011 	// if there is a chance of animated vertex colors, it's a dynamic batch
9012 	if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9013 	{
9014 		if (!dynamicvertex)
9015 		{
9016 			r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9017 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9018 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9019 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9020 		}
9021 		dynamicvertex = true;
9022 		needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9023 	}
9024 
9025 	for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9026 	{
9027 		switch (deform->deform)
9028 		{
9029 		default:
9030 		case Q3DEFORM_PROJECTIONSHADOW:
9031 		case Q3DEFORM_TEXT0:
9032 		case Q3DEFORM_TEXT1:
9033 		case Q3DEFORM_TEXT2:
9034 		case Q3DEFORM_TEXT3:
9035 		case Q3DEFORM_TEXT4:
9036 		case Q3DEFORM_TEXT5:
9037 		case Q3DEFORM_TEXT6:
9038 		case Q3DEFORM_TEXT7:
9039 		case Q3DEFORM_NONE:
9040 			break;
9041 		case Q3DEFORM_AUTOSPRITE:
9042 			if (!dynamicvertex)
9043 			{
9044 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9045 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9046 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9047 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9048 			}
9049 			dynamicvertex = true;
9050 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9051 			needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9052 			break;
9053 		case Q3DEFORM_AUTOSPRITE2:
9054 			if (!dynamicvertex)
9055 			{
9056 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9057 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9058 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9059 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9060 			}
9061 			dynamicvertex = true;
9062 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9063 			needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9064 			break;
9065 		case Q3DEFORM_NORMAL:
9066 			if (!dynamicvertex)
9067 			{
9068 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9069 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9070 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9071 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9072 			}
9073 			dynamicvertex = true;
9074 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9075 			needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9076 			break;
9077 		case Q3DEFORM_WAVE:
9078 			if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9079 				break; // if wavefunc is a nop, ignore this transform
9080 			if (!dynamicvertex)
9081 			{
9082 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9083 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9084 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9085 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9086 			}
9087 			dynamicvertex = true;
9088 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9089 			needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9090 			break;
9091 		case Q3DEFORM_BULGE:
9092 			if (!dynamicvertex)
9093 			{
9094 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9095 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9096 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9097 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9098 			}
9099 			dynamicvertex = true;
9100 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9101 			needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9102 			break;
9103 		case Q3DEFORM_MOVE:
9104 			if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9105 				break; // if wavefunc is a nop, ignore this transform
9106 			if (!dynamicvertex)
9107 			{
9108 				r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9109 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9110 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9111 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9112 			}
9113 			dynamicvertex = true;
9114 			batchneed |= BATCHNEED_ARRAY_VERTEX;
9115 			needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9116 			break;
9117 		}
9118 	}
9119 	if (rsurface.texture->materialshaderpass)
9120 	{
9121 		switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9122 		{
9123 		default:
9124 		case Q3TCGEN_TEXTURE:
9125 			break;
9126 		case Q3TCGEN_LIGHTMAP:
9127 			if (!dynamicvertex)
9128 			{
9129 				r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9130 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9131 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9132 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9133 			}
9134 			dynamicvertex = true;
9135 			batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9136 			needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9137 			break;
9138 		case Q3TCGEN_VECTOR:
9139 			if (!dynamicvertex)
9140 			{
9141 				r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9142 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9143 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9144 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9145 			}
9146 			dynamicvertex = true;
9147 			batchneed |= BATCHNEED_ARRAY_VERTEX;
9148 			needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9149 			break;
9150 		case Q3TCGEN_ENVIRONMENT:
9151 			if (!dynamicvertex)
9152 			{
9153 				r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9154 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9155 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9156 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9157 			}
9158 			dynamicvertex = true;
9159 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9160 			needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9161 			break;
9162 		}
9163 		if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9164 		{
9165 			if (!dynamicvertex)
9166 			{
9167 				r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9168 				r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9169 				r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9170 				r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9171 			}
9172 			dynamicvertex = true;
9173 			batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9174 			needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9175 		}
9176 	}
9177 
9178 	if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9179 	{
9180 		if (!dynamicvertex)
9181 		{
9182 			r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9183 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9184 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9185 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9186 		}
9187 		dynamicvertex = true;
9188 		needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9189 	}
9190 
9191 	// when the model data has no vertex buffer (dynamic mesh), we need to
9192 	// eliminate gaps
9193 	if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9194 		batchneed |= BATCHNEED_NOGAPS;
9195 
9196 	// the caller can specify BATCHNEED_NOGAPS to force a batch with
9197 	// firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9198 	// we ensure this by treating the vertex batch as dynamic...
9199 	if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9200 	{
9201 		if (!dynamicvertex)
9202 		{
9203 			r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9204 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9205 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9206 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9207 		}
9208 		dynamicvertex = true;
9209 	}
9210 
9211 	if (dynamicvertex)
9212 	{
9213 		// when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9214 		if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9215 		if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9216 		if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9217 		if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9218 		if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9219 		if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9220 		if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9221 	}
9222 
9223 	// if needsupdate, we have to do a dynamic vertex batch for sure
9224 	if (needsupdate & batchneed)
9225 	{
9226 		if (!dynamicvertex)
9227 		{
9228 			r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9229 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9230 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9231 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9232 		}
9233 		dynamicvertex = true;
9234 	}
9235 
9236 	// see if we need to build vertexmesh from arrays
9237 	if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9238 	{
9239 		if (!dynamicvertex)
9240 		{
9241 			r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9242 			r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9243 			r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9244 			r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9245 		}
9246 		dynamicvertex = true;
9247 	}
9248 
9249 	// if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9250 	if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9251 		batchneed |= BATCHNEED_ARRAY_SKELETAL;
9252 
9253 	rsurface.batchvertex3f = rsurface.modelvertex3f;
9254 	rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9255 	rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9256 	rsurface.batchsvector3f = rsurface.modelsvector3f;
9257 	rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9258 	rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9259 	rsurface.batchtvector3f = rsurface.modeltvector3f;
9260 	rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9261 	rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9262 	rsurface.batchnormal3f = rsurface.modelnormal3f;
9263 	rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9264 	rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9265 	rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9266 	rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9267 	rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9268 	rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9269 	rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9270 	rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9271 	rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9272 	rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9273 	rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9274 	rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9275 	rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9276 	rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9277 	rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9278 	rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9279 	rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9280 	rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9281 	rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9282 	rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9283 	rsurface.batchelement3i = rsurface.modelelement3i;
9284 	rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9285 	rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9286 	rsurface.batchelement3s = rsurface.modelelement3s;
9287 	rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9288 	rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9289 	rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9290 	rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9291 	rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9292 	rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9293 	rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9294 
9295 	// if any dynamic vertex processing has to occur in software, we copy the
9296 	// entire surface list together before processing to rebase the vertices
9297 	// to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9298 	//
9299 	// if any gaps exist and we do not have a static vertex buffer, we have to
9300 	// copy the surface list together to avoid wasting upload bandwidth on the
9301 	// vertices in the gaps.
9302 	//
9303 	// if gaps exist and we have a static vertex buffer, we can choose whether
9304 	// to combine the index buffer ranges into one dynamic index buffer or
9305 	// simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9306 	//
9307 	// in many cases the batch is reduced to one draw call.
9308 
9309 	rsurface.batchmultidraw = false;
9310 	rsurface.batchmultidrawnumsurfaces = 0;
9311 	rsurface.batchmultidrawsurfacelist = NULL;
9312 
9313 	if (!dynamicvertex)
9314 	{
9315 		// static vertex data, just set pointers...
9316 		rsurface.batchgeneratedvertex = false;
9317 		// if there are gaps, we want to build a combined index buffer,
9318 		// otherwise use the original static buffer with an appropriate offset
9319 		if (gaps)
9320 		{
9321 			r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9322 			r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9323 			r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9324 			r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9325 			if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9326 			{
9327 				rsurface.batchmultidraw = true;
9328 				rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9329 				rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9330 				return;
9331 			}
9332 			// build a new triangle elements array for this batch
9333 			rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9334 			rsurface.batchfirsttriangle = 0;
9335 			numtriangles = 0;
9336 			for (i = 0;i < texturenumsurfaces;i++)
9337 			{
9338 				surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9339 				surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9340 				memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9341 				numtriangles += surfacenumtriangles;
9342 			}
9343 			rsurface.batchelement3i_indexbuffer = NULL;
9344 			rsurface.batchelement3i_bufferoffset = 0;
9345 			rsurface.batchelement3s = NULL;
9346 			rsurface.batchelement3s_indexbuffer = NULL;
9347 			rsurface.batchelement3s_bufferoffset = 0;
9348 			if (endvertex <= 65536)
9349 			{
9350 				// make a 16bit (unsigned short) index array if possible
9351 				rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9352 				for (i = 0;i < numtriangles*3;i++)
9353 					rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9354 			}
9355 			// upload buffer data for the copytriangles batch
9356 			if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9357 			{
9358 				if (rsurface.batchelement3s)
9359 					rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9360 				else if (rsurface.batchelement3i)
9361 					rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9362 			}
9363 		}
9364 		else
9365 		{
9366 			r_refdef.stats[r_stat_batch_fast_batches] += 1;
9367 			r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9368 			r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9369 			r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9370 		}
9371 		return;
9372 	}
9373 
9374 	// something needs software processing, do it for real...
9375 	// we only directly handle separate array data in this case and then
9376 	// generate interleaved data if needed...
9377 	rsurface.batchgeneratedvertex = true;
9378 	r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9379 	r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9380 	r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9381 	r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9382 
9383 	// now copy the vertex data into a combined array and make an index array
9384 	// (this is what Quake3 does all the time)
9385 	// we also apply any skeletal animation here that would have been done in
9386 	// the vertex shader, because most of the dynamic vertex animation cases
9387 	// need actual vertex positions and normals
9388 	//if (dynamicvertex)
9389 	{
9390 		rsurface.batchvertexmesh = NULL;
9391 		rsurface.batchvertexmesh_vertexbuffer = NULL;
9392 		rsurface.batchvertexmesh_bufferoffset = 0;
9393 		rsurface.batchvertex3f = NULL;
9394 		rsurface.batchvertex3f_vertexbuffer = NULL;
9395 		rsurface.batchvertex3f_bufferoffset = 0;
9396 		rsurface.batchsvector3f = NULL;
9397 		rsurface.batchsvector3f_vertexbuffer = NULL;
9398 		rsurface.batchsvector3f_bufferoffset = 0;
9399 		rsurface.batchtvector3f = NULL;
9400 		rsurface.batchtvector3f_vertexbuffer = NULL;
9401 		rsurface.batchtvector3f_bufferoffset = 0;
9402 		rsurface.batchnormal3f = NULL;
9403 		rsurface.batchnormal3f_vertexbuffer = NULL;
9404 		rsurface.batchnormal3f_bufferoffset = 0;
9405 		rsurface.batchlightmapcolor4f = NULL;
9406 		rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9407 		rsurface.batchlightmapcolor4f_bufferoffset = 0;
9408 		rsurface.batchtexcoordtexture2f = NULL;
9409 		rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9410 		rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9411 		rsurface.batchtexcoordlightmap2f = NULL;
9412 		rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9413 		rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9414 		rsurface.batchskeletalindex4ub = NULL;
9415 		rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9416 		rsurface.batchskeletalindex4ub_bufferoffset = 0;
9417 		rsurface.batchskeletalweight4ub = NULL;
9418 		rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9419 		rsurface.batchskeletalweight4ub_bufferoffset = 0;
9420 		rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9421 		rsurface.batchelement3i_indexbuffer = NULL;
9422 		rsurface.batchelement3i_bufferoffset = 0;
9423 		rsurface.batchelement3s = NULL;
9424 		rsurface.batchelement3s_indexbuffer = NULL;
9425 		rsurface.batchelement3s_bufferoffset = 0;
9426 		rsurface.batchskeletaltransform3x4buffer = NULL;
9427 		rsurface.batchskeletaltransform3x4offset = 0;
9428 		rsurface.batchskeletaltransform3x4size = 0;
9429 		// we'll only be setting up certain arrays as needed
9430 		if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9431 			rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9432 		if (batchneed & BATCHNEED_ARRAY_VERTEX)
9433 			rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9434 		if (batchneed & BATCHNEED_ARRAY_NORMAL)
9435 			rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436 		if (batchneed & BATCHNEED_ARRAY_VECTOR)
9437 		{
9438 			rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9439 			rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9440 		}
9441 		if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9442 			rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9443 		if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9444 			rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9445 		if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9446 			rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9447 		if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9448 		{
9449 			rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9450 			rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9451 		}
9452 		numvertices = 0;
9453 		numtriangles = 0;
9454 		for (i = 0;i < texturenumsurfaces;i++)
9455 		{
9456 			surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9457 			surfacenumvertices = texturesurfacelist[i]->num_vertices;
9458 			surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9459 			surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9460 			// copy only the data requested
9461 			if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9462 				memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9463 			if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9464 			{
9465 				if (batchneed & BATCHNEED_ARRAY_VERTEX)
9466 				{
9467 					if (rsurface.batchvertex3f)
9468 						memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9469 					else
9470 						memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9471 				}
9472 				if (batchneed & BATCHNEED_ARRAY_NORMAL)
9473 				{
9474 					if (rsurface.modelnormal3f)
9475 						memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9476 					else
9477 						memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9478 				}
9479 				if (batchneed & BATCHNEED_ARRAY_VECTOR)
9480 				{
9481 					if (rsurface.modelsvector3f)
9482 					{
9483 						memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9484 						memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9485 					}
9486 					else
9487 					{
9488 						memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9489 						memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9490 					}
9491 				}
9492 				if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9493 				{
9494 					if (rsurface.modellightmapcolor4f)
9495 						memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9496 					else
9497 						memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9498 				}
9499 				if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9500 				{
9501 					if (rsurface.modeltexcoordtexture2f)
9502 						memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9503 					else
9504 						memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9505 				}
9506 				if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9507 				{
9508 					if (rsurface.modeltexcoordlightmap2f)
9509 						memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9510 					else
9511 						memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9512 				}
9513 				if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9514 				{
9515 					if (rsurface.modelskeletalindex4ub)
9516 					{
9517 						memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9518 						memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9519 					}
9520 					else
9521 					{
9522 						memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9523 						memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9524 						ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9525 						for (j = 0;j < surfacenumvertices;j++)
9526 							ub[j*4] = 255;
9527 					}
9528 				}
9529 			}
9530 			RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9531 			numvertices += surfacenumvertices;
9532 			numtriangles += surfacenumtriangles;
9533 		}
9534 
9535 		// generate a 16bit index array as well if possible
9536 		// (in general, dynamic batches fit)
9537 		if (numvertices <= 65536)
9538 		{
9539 			rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9540 			for (i = 0;i < numtriangles*3;i++)
9541 				rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9542 		}
9543 
9544 		// since we've copied everything, the batch now starts at 0
9545 		rsurface.batchfirstvertex = 0;
9546 		rsurface.batchnumvertices = batchnumvertices;
9547 		rsurface.batchfirsttriangle = 0;
9548 		rsurface.batchnumtriangles = batchnumtriangles;
9549 	}
9550 
9551 	// apply skeletal animation that would have been done in the vertex shader
9552 	if (rsurface.batchskeletaltransform3x4)
9553 	{
9554 		const unsigned char *si;
9555 		const unsigned char *sw;
9556 		const float *t[4];
9557 		const float *b = rsurface.batchskeletaltransform3x4;
9558 		float *vp, *vs, *vt, *vn;
9559 		float w[4];
9560 		float m[3][4], n[3][4];
9561 		float tp[3], ts[3], tt[3], tn[3];
9562 		r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9563 		r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9564 		r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9565 		r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9566 		si = rsurface.batchskeletalindex4ub;
9567 		sw = rsurface.batchskeletalweight4ub;
9568 		vp = rsurface.batchvertex3f;
9569 		vs = rsurface.batchsvector3f;
9570 		vt = rsurface.batchtvector3f;
9571 		vn = rsurface.batchnormal3f;
9572 		memset(m[0], 0, sizeof(m));
9573 		memset(n[0], 0, sizeof(n));
9574 		for (i = 0;i < batchnumvertices;i++)
9575 		{
9576 			t[0] = b + si[0]*12;
9577 			if (sw[0] == 255)
9578 			{
9579 				// common case - only one matrix
9580 				m[0][0] = t[0][ 0];
9581 				m[0][1] = t[0][ 1];
9582 				m[0][2] = t[0][ 2];
9583 				m[0][3] = t[0][ 3];
9584 				m[1][0] = t[0][ 4];
9585 				m[1][1] = t[0][ 5];
9586 				m[1][2] = t[0][ 6];
9587 				m[1][3] = t[0][ 7];
9588 				m[2][0] = t[0][ 8];
9589 				m[2][1] = t[0][ 9];
9590 				m[2][2] = t[0][10];
9591 				m[2][3] = t[0][11];
9592 			}
9593 			else if (sw[2] + sw[3])
9594 			{
9595 				// blend 4 matrices
9596 				t[1] = b + si[1]*12;
9597 				t[2] = b + si[2]*12;
9598 				t[3] = b + si[3]*12;
9599 				w[0] = sw[0] * (1.0f / 255.0f);
9600 				w[1] = sw[1] * (1.0f / 255.0f);
9601 				w[2] = sw[2] * (1.0f / 255.0f);
9602 				w[3] = sw[3] * (1.0f / 255.0f);
9603 				// blend the matrices
9604 				m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9605 				m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9606 				m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9607 				m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9608 				m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9609 				m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9610 				m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9611 				m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9612 				m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9613 				m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9614 				m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9615 				m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9616 			}
9617 			else
9618 			{
9619 				// blend 2 matrices
9620 				t[1] = b + si[1]*12;
9621 				w[0] = sw[0] * (1.0f / 255.0f);
9622 				w[1] = sw[1] * (1.0f / 255.0f);
9623 				// blend the matrices
9624 				m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9625 				m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9626 				m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9627 				m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9628 				m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9629 				m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9630 				m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9631 				m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9632 				m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9633 				m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9634 				m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9635 				m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9636 			}
9637 			si += 4;
9638 			sw += 4;
9639 			// modify the vertex
9640 			VectorCopy(vp, tp);
9641 			vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9642 			vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9643 			vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9644 			vp += 3;
9645 			if (vn)
9646 			{
9647 				// the normal transformation matrix is a set of cross products...
9648 				CrossProduct(m[1], m[2], n[0]);
9649 				CrossProduct(m[2], m[0], n[1]);
9650 				CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9651 				VectorCopy(vn, tn);
9652 				vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9653 				vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9654 				vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9655 				VectorNormalize(vn);
9656 				vn += 3;
9657 				if (vs)
9658 				{
9659 					VectorCopy(vs, ts);
9660 					vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9661 					vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9662 					vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9663 					VectorNormalize(vs);
9664 					vs += 3;
9665 					VectorCopy(vt, tt);
9666 					vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9667 					vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9668 					vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9669 					VectorNormalize(vt);
9670 					vt += 3;
9671 				}
9672 			}
9673 		}
9674 		rsurface.batchskeletaltransform3x4 = NULL;
9675 		rsurface.batchskeletalnumtransforms = 0;
9676 	}
9677 
9678 	// q1bsp surfaces rendered in vertex color mode have to have colors
9679 	// calculated based on lightstyles
9680 	if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9681 	{
9682 		// generate color arrays for the surfaces in this list
9683 		int c[4];
9684 		int scale;
9685 		int size3;
9686 		const int *offsets;
9687 		const unsigned char *lm;
9688 		rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9689 		rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9690 		rsurface.batchlightmapcolor4f_bufferoffset = 0;
9691 		numvertices = 0;
9692 		for (i = 0;i < texturenumsurfaces;i++)
9693 		{
9694 			surface = texturesurfacelist[i];
9695 			offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9696 			surfacenumvertices = surface->num_vertices;
9697 			if (surface->lightmapinfo->samples)
9698 			{
9699 				for (j = 0;j < surfacenumvertices;j++)
9700 				{
9701 					lm = surface->lightmapinfo->samples + offsets[j];
9702 					scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9703 					VectorScale(lm, scale, c);
9704 					if (surface->lightmapinfo->styles[1] != 255)
9705 					{
9706 						size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9707 						lm += size3;
9708 						scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9709 						VectorMA(c, scale, lm, c);
9710 						if (surface->lightmapinfo->styles[2] != 255)
9711 						{
9712 							lm += size3;
9713 							scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9714 							VectorMA(c, scale, lm, c);
9715 							if (surface->lightmapinfo->styles[3] != 255)
9716 							{
9717 								lm += size3;
9718 								scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9719 								VectorMA(c, scale, lm, c);
9720 							}
9721 						}
9722 					}
9723 					c[0] >>= 7;
9724 					c[1] >>= 7;
9725 					c[2] >>= 7;
9726 					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);
9727 					numvertices++;
9728 				}
9729 			}
9730 			else
9731 			{
9732 				for (j = 0;j < surfacenumvertices;j++)
9733 				{
9734 					Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9735 					numvertices++;
9736 				}
9737 			}
9738 		}
9739 	}
9740 
9741 	// if vertices are deformed (sprite flares and things in maps, possibly
9742 	// water waves, bulges and other deformations), modify the copied vertices
9743 	// in place
9744 	for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9745 	{
9746 		float scale;
9747 		switch (deform->deform)
9748 		{
9749 		default:
9750 		case Q3DEFORM_PROJECTIONSHADOW:
9751 		case Q3DEFORM_TEXT0:
9752 		case Q3DEFORM_TEXT1:
9753 		case Q3DEFORM_TEXT2:
9754 		case Q3DEFORM_TEXT3:
9755 		case Q3DEFORM_TEXT4:
9756 		case Q3DEFORM_TEXT5:
9757 		case Q3DEFORM_TEXT6:
9758 		case Q3DEFORM_TEXT7:
9759 		case Q3DEFORM_NONE:
9760 			break;
9761 		case Q3DEFORM_AUTOSPRITE:
9762 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9763 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9764 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9765 			VectorNormalize(newforward);
9766 			VectorNormalize(newright);
9767 			VectorNormalize(newup);
9768 //			rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9769 //			rsurface.batchvertex3f_vertexbuffer = NULL;
9770 //			rsurface.batchvertex3f_bufferoffset = 0;
9771 //			rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9772 //			rsurface.batchsvector3f_vertexbuffer = NULL;
9773 //			rsurface.batchsvector3f_bufferoffset = 0;
9774 //			rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9775 //			rsurface.batchtvector3f_vertexbuffer = NULL;
9776 //			rsurface.batchtvector3f_bufferoffset = 0;
9777 //			rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9778 //			rsurface.batchnormal3f_vertexbuffer = NULL;
9779 //			rsurface.batchnormal3f_bufferoffset = 0;
9780 			// sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9781 			if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9782 				Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9783 			if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9784 				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);
9785 			// a single autosprite surface can contain multiple sprites...
9786 			for (j = 0;j < batchnumvertices - 3;j += 4)
9787 			{
9788 				VectorClear(center);
9789 				for (i = 0;i < 4;i++)
9790 					VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9791 				VectorScale(center, 0.25f, center);
9792 				VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9793 				VectorCopy(rsurface.batchsvector3f + 3*j, right);
9794 				VectorCopy(rsurface.batchtvector3f + 3*j, up);
9795 				for (i = 0;i < 4;i++)
9796 				{
9797 					VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9798 					VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9799 				}
9800 			}
9801 			// if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9802 			Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9803 			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);
9804 			break;
9805 		case Q3DEFORM_AUTOSPRITE2:
9806 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9807 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9808 			Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9809 			VectorNormalize(newforward);
9810 			VectorNormalize(newright);
9811 			VectorNormalize(newup);
9812 //			rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9813 //			rsurface.batchvertex3f_vertexbuffer = NULL;
9814 //			rsurface.batchvertex3f_bufferoffset = 0;
9815 			{
9816 				const float *v1, *v2;
9817 				vec3_t start, end;
9818 				float f, l;
9819 				struct
9820 				{
9821 					float length2;
9822 					const float *v1;
9823 					const float *v2;
9824 				}
9825 				shortest[2];
9826 				memset(shortest, 0, sizeof(shortest));
9827 				// a single autosprite surface can contain multiple sprites...
9828 				for (j = 0;j < batchnumvertices - 3;j += 4)
9829 				{
9830 					VectorClear(center);
9831 					for (i = 0;i < 4;i++)
9832 						VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9833 					VectorScale(center, 0.25f, center);
9834 					// find the two shortest edges, then use them to define the
9835 					// axis vectors for rotating around the central axis
9836 					for (i = 0;i < 6;i++)
9837 					{
9838 						v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9839 						v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9840 						l = VectorDistance2(v1, v2);
9841 						// this length bias tries to make sense of square polygons, assuming they are meant to be upright
9842 						if (v1[2] != v2[2])
9843 							l += (1.0f / 1024.0f);
9844 						if (shortest[0].length2 > l || i == 0)
9845 						{
9846 							shortest[1] = shortest[0];
9847 							shortest[0].length2 = l;
9848 							shortest[0].v1 = v1;
9849 							shortest[0].v2 = v2;
9850 						}
9851 						else if (shortest[1].length2 > l || i == 1)
9852 						{
9853 							shortest[1].length2 = l;
9854 							shortest[1].v1 = v1;
9855 							shortest[1].v2 = v2;
9856 						}
9857 					}
9858 					VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9859 					VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9860 					// this calculates the right vector from the shortest edge
9861 					// and the up vector from the edge midpoints
9862 					VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9863 					VectorNormalize(right);
9864 					VectorSubtract(end, start, up);
9865 					VectorNormalize(up);
9866 					// calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9867 					VectorSubtract(rsurface.localvieworigin, center, forward);
9868 					//Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9869 					VectorNegate(forward, forward);
9870 					VectorReflect(forward, 0, up, forward);
9871 					VectorNormalize(forward);
9872 					CrossProduct(up, forward, newright);
9873 					VectorNormalize(newright);
9874 					// rotate the quad around the up axis vector, this is made
9875 					// especially easy by the fact we know the quad is flat,
9876 					// so we only have to subtract the center position and
9877 					// measure distance along the right vector, and then
9878 					// multiply that by the newright vector and add back the
9879 					// center position
9880 					// we also need to subtract the old position to undo the
9881 					// displacement from the center, which we do with a
9882 					// DotProduct, the subtraction/addition of center is also
9883 					// optimized into DotProducts here
9884 					l = DotProduct(right, center);
9885 					for (i = 0;i < 4;i++)
9886 					{
9887 						v1 = rsurface.batchvertex3f + 3*(j+i);
9888 						f = DotProduct(right, v1) - l;
9889 						VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9890 					}
9891 				}
9892 			}
9893 			if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9894 			{
9895 //				rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9896 //				rsurface.batchnormal3f_vertexbuffer = NULL;
9897 //				rsurface.batchnormal3f_bufferoffset = 0;
9898 				Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9899 			}
9900 			if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9901 			{
9902 //				rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9903 //				rsurface.batchsvector3f_vertexbuffer = NULL;
9904 //				rsurface.batchsvector3f_bufferoffset = 0;
9905 //				rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9906 //				rsurface.batchtvector3f_vertexbuffer = NULL;
9907 //				rsurface.batchtvector3f_bufferoffset = 0;
9908 				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);
9909 			}
9910 			break;
9911 		case Q3DEFORM_NORMAL:
9912 			// deform the normals to make reflections wavey
9913 			rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9914 			rsurface.batchnormal3f_vertexbuffer = NULL;
9915 			rsurface.batchnormal3f_bufferoffset = 0;
9916 			for (j = 0;j < batchnumvertices;j++)
9917 			{
9918 				float vertex[3];
9919 				float *normal = rsurface.batchnormal3f + 3*j;
9920 				VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9921 				normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9922 				normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9923 				normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9924 				VectorNormalize(normal);
9925 			}
9926 			if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9927 			{
9928 //				rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9929 //				rsurface.batchsvector3f_vertexbuffer = NULL;
9930 //				rsurface.batchsvector3f_bufferoffset = 0;
9931 //				rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9932 //				rsurface.batchtvector3f_vertexbuffer = NULL;
9933 //				rsurface.batchtvector3f_bufferoffset = 0;
9934 				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);
9935 			}
9936 			break;
9937 		case Q3DEFORM_WAVE:
9938 			// deform vertex array to make wavey water and flags and such
9939 			waveparms[0] = deform->waveparms[0];
9940 			waveparms[1] = deform->waveparms[1];
9941 			waveparms[2] = deform->waveparms[2];
9942 			waveparms[3] = deform->waveparms[3];
9943 			if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9944 				break; // if wavefunc is a nop, don't make a dynamic vertex array
9945 			// this is how a divisor of vertex influence on deformation
9946 			animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9947 			scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9948 //			rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9949 //			rsurface.batchvertex3f_vertexbuffer = NULL;
9950 //			rsurface.batchvertex3f_bufferoffset = 0;
9951 //			rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9952 //			rsurface.batchnormal3f_vertexbuffer = NULL;
9953 //			rsurface.batchnormal3f_bufferoffset = 0;
9954 			for (j = 0;j < batchnumvertices;j++)
9955 			{
9956 				// if the wavefunc depends on time, evaluate it per-vertex
9957 				if (waveparms[3])
9958 				{
9959 					waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9960 					scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9961 				}
9962 				VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9963 			}
9964 			// if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9965 			Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9966 			if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9967 			{
9968 //				rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9969 //				rsurface.batchsvector3f_vertexbuffer = NULL;
9970 //				rsurface.batchsvector3f_bufferoffset = 0;
9971 //				rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9972 //				rsurface.batchtvector3f_vertexbuffer = NULL;
9973 //				rsurface.batchtvector3f_bufferoffset = 0;
9974 				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);
9975 			}
9976 			break;
9977 		case Q3DEFORM_BULGE:
9978 			// deform vertex array to make the surface have moving bulges
9979 //			rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9980 //			rsurface.batchvertex3f_vertexbuffer = NULL;
9981 //			rsurface.batchvertex3f_bufferoffset = 0;
9982 //			rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9983 //			rsurface.batchnormal3f_vertexbuffer = NULL;
9984 //			rsurface.batchnormal3f_bufferoffset = 0;
9985 			for (j = 0;j < batchnumvertices;j++)
9986 			{
9987 				scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9988 				VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9989 			}
9990 			// if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9991 			Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9992 			if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9993 			{
9994 //				rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9995 //				rsurface.batchsvector3f_vertexbuffer = NULL;
9996 //				rsurface.batchsvector3f_bufferoffset = 0;
9997 //				rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9998 //				rsurface.batchtvector3f_vertexbuffer = NULL;
9999 //				rsurface.batchtvector3f_bufferoffset = 0;
10000 				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);
10001 			}
10002 			break;
10003 		case Q3DEFORM_MOVE:
10004 			// deform vertex array
10005 			if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10006 				break; // if wavefunc is a nop, don't make a dynamic vertex array
10007 			scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10008 			VectorScale(deform->parms, scale, waveparms);
10009 //			rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10010 //			rsurface.batchvertex3f_vertexbuffer = NULL;
10011 //			rsurface.batchvertex3f_bufferoffset = 0;
10012 			for (j = 0;j < batchnumvertices;j++)
10013 				VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10014 			break;
10015 		}
10016 	}
10017 
10018 	if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10019 	{
10020 	// generate texcoords based on the chosen texcoord source
10021 		switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10022 		{
10023 		default:
10024 		case Q3TCGEN_TEXTURE:
10025 			break;
10026 		case Q3TCGEN_LIGHTMAP:
10027 	//		rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10028 	//		rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10029 	//		rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10030 			if (rsurface.batchtexcoordlightmap2f)
10031 				memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10032 			break;
10033 		case Q3TCGEN_VECTOR:
10034 	//		rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10035 	//		rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10036 	//		rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10037 			for (j = 0;j < batchnumvertices;j++)
10038 			{
10039 				rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10040 				rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10041 			}
10042 			break;
10043 		case Q3TCGEN_ENVIRONMENT:
10044 			// make environment reflections using a spheremap
10045 			rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10046 			rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10047 			rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10048 			for (j = 0;j < batchnumvertices;j++)
10049 			{
10050 				// identical to Q3A's method, but executed in worldspace so
10051 				// carried models can be shiny too
10052 
10053 				float viewer[3], d, reflected[3], worldreflected[3];
10054 
10055 				VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10056 				// VectorNormalize(viewer);
10057 
10058 				d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10059 
10060 				reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10061 				reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10062 				reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10063 				// note: this is proportinal to viewer, so we can normalize later
10064 
10065 				Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10066 				VectorNormalize(worldreflected);
10067 
10068 				// note: this sphere map only uses world x and z!
10069 				// so positive and negative y will LOOK THE SAME.
10070 				rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10071 				rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10072 			}
10073 			break;
10074 		}
10075 		// the only tcmod that needs software vertex processing is turbulent, so
10076 		// check for it here and apply the changes if needed
10077 		// and we only support that as the first one
10078 		// (handling a mixture of turbulent and other tcmods would be problematic
10079 		//  without punting it entirely to a software path)
10080 		if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10081 		{
10082 			amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10083 			animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10084 	//		rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10085 	//		rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10086 	//		rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10087 			for (j = 0;j < batchnumvertices;j++)
10088 			{
10089 				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);
10090 				rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10091 			}
10092 		}
10093 	}
10094 
10095 	if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10096 	{
10097 		// convert the modified arrays to vertex structs
10098 //		rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10099 //		rsurface.batchvertexmesh_vertexbuffer = NULL;
10100 //		rsurface.batchvertexmesh_bufferoffset = 0;
10101 		if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10102 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10103 				VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10104 		if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10105 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10106 				VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10107 		if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10108 		{
10109 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10110 			{
10111 				VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10112 				VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10113 			}
10114 		}
10115 		if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10116 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10117 				Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10118 		if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10119 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10120 				Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10121 		if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10122 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10123 				Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10124 		if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10125 		{
10126 			for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10127 			{
10128 				Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10129 				Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10130 			}
10131 		}
10132 	}
10133 
10134 	// upload buffer data for the dynamic batch
10135 	if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10136 	{
10137 		if (rsurface.batchvertexmesh)
10138 			rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10139 		else
10140 		{
10141 			if (rsurface.batchvertex3f)
10142 				rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10143 			if (rsurface.batchsvector3f)
10144 				rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10145 			if (rsurface.batchtvector3f)
10146 				rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10147 			if (rsurface.batchnormal3f)
10148 				rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10149 			if (rsurface.batchlightmapcolor4f)
10150 				rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10151 			if (rsurface.batchtexcoordtexture2f)
10152 				rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10153 			if (rsurface.batchtexcoordlightmap2f)
10154 				rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10155 			if (rsurface.batchskeletalindex4ub)
10156 				rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10157 			if (rsurface.batchskeletalweight4ub)
10158 				rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10159 		}
10160 		if (rsurface.batchelement3s)
10161 			rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10162 		else if (rsurface.batchelement3i)
10163 			rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10164 	}
10165 }
10166 
RSurf_DrawBatch(void)10167 void RSurf_DrawBatch(void)
10168 {
10169 	// sometimes a zero triangle surface (usually a degenerate patch) makes it
10170 	// through the pipeline, killing it earlier in the pipeline would have
10171 	// per-surface overhead rather than per-batch overhead, so it's best to
10172 	// reject it here, before it hits glDraw.
10173 	if (rsurface.batchnumtriangles == 0)
10174 		return;
10175 #if 0
10176 	// batch debugging code
10177 	if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10178 	{
10179 		int i;
10180 		int j;
10181 		int c;
10182 		const int *e;
10183 		e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10184 		for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10185 		{
10186 			c = e[i];
10187 			for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10188 			{
10189 				if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10190 				{
10191 					if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10192 						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);
10193 					break;
10194 				}
10195 			}
10196 		}
10197 	}
10198 #endif
10199 	if (rsurface.batchmultidraw)
10200 	{
10201 		// issue multiple draws rather than copying index data
10202 		int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10203 		const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10204 		int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10205 		for (i = 0;i < numsurfaces;)
10206 		{
10207 			// combine consecutive surfaces as one draw
10208 			for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10209 				if (surfacelist[j] != surfacelist[k] + 1)
10210 					break;
10211 			firstvertex = surfacelist[i]->num_firstvertex;
10212 			endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10213 			firsttriangle = surfacelist[i]->num_firsttriangle;
10214 			endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10215 			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);
10216 			i = j;
10217 		}
10218 	}
10219 	else
10220 	{
10221 		// there is only one consecutive run of index data (may have been combined)
10222 		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);
10223 	}
10224 }
10225 
RSurf_FindWaterPlaneForSurface(const msurface_t * surface)10226 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10227 {
10228 	// pick the closest matching water plane
10229 	int planeindex, vertexindex, bestplaneindex = -1;
10230 	float d, bestd;
10231 	vec3_t vert;
10232 	const float *v;
10233 	r_waterstate_waterplane_t *p;
10234 	qboolean prepared = false;
10235 	bestd = 0;
10236 	for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10237 	{
10238 		if(p->camera_entity != rsurface.texture->camera_entity)
10239 			continue;
10240 		d = 0;
10241 		if(!prepared)
10242 		{
10243 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10244 			prepared = true;
10245 			if(rsurface.batchnumvertices == 0)
10246 				break;
10247 		}
10248 		for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10249 		{
10250 			Matrix4x4_Transform(&rsurface.matrix, v, vert);
10251 			d += fabs(PlaneDiff(vert, &p->plane));
10252 		}
10253 		if (bestd > d || bestplaneindex < 0)
10254 		{
10255 			bestd = d;
10256 			bestplaneindex = planeindex;
10257 		}
10258 	}
10259 	return bestplaneindex;
10260 	// NOTE: this MAY return a totally unrelated water plane; we can ignore
10261 	// this situation though, as it might be better to render single larger
10262 	// batches with useless stuff (backface culled for example) than to
10263 	// render multiple smaller batches
10264 }
10265 
RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)10266 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10267 {
10268 	int i;
10269 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10270 	rsurface.passcolor4f_vertexbuffer = 0;
10271 	rsurface.passcolor4f_bufferoffset = 0;
10272 	for (i = 0;i < rsurface.batchnumvertices;i++)
10273 		Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10274 }
10275 
RSurf_DrawBatch_GL11_ApplyFog(void)10276 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10277 {
10278 	int i;
10279 	float f;
10280 	const float *v;
10281 	const float *c;
10282 	float *c2;
10283 	if (rsurface.passcolor4f)
10284 	{
10285 		// generate color arrays
10286 		c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10287 		rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10288 		rsurface.passcolor4f_vertexbuffer = 0;
10289 		rsurface.passcolor4f_bufferoffset = 0;
10290 		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)
10291 		{
10292 			f = RSurf_FogVertex(v);
10293 			c2[0] = c[0] * f;
10294 			c2[1] = c[1] * f;
10295 			c2[2] = c[2] * f;
10296 			c2[3] = c[3];
10297 		}
10298 	}
10299 	else
10300 	{
10301 		rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10302 		rsurface.passcolor4f_vertexbuffer = 0;
10303 		rsurface.passcolor4f_bufferoffset = 0;
10304 		for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10305 		{
10306 			f = RSurf_FogVertex(v);
10307 			c2[0] = f;
10308 			c2[1] = f;
10309 			c2[2] = f;
10310 			c2[3] = 1;
10311 		}
10312 	}
10313 }
10314 
RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)10315 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10316 {
10317 	int i;
10318 	float f;
10319 	const float *v;
10320 	const float *c;
10321 	float *c2;
10322 	if (!rsurface.passcolor4f)
10323 		return;
10324 	c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10325 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10326 	rsurface.passcolor4f_vertexbuffer = 0;
10327 	rsurface.passcolor4f_bufferoffset = 0;
10328 	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)
10329 	{
10330 		f = RSurf_FogVertex(v);
10331 		c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10332 		c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10333 		c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10334 		c2[3] = c[3];
10335 	}
10336 }
10337 
RSurf_DrawBatch_GL11_ApplyColor(float r,float g,float b,float a)10338 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10339 {
10340 	int i;
10341 	const float *c;
10342 	float *c2;
10343 	if (!rsurface.passcolor4f)
10344 		return;
10345 	c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10346 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10347 	rsurface.passcolor4f_vertexbuffer = 0;
10348 	rsurface.passcolor4f_bufferoffset = 0;
10349 	for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10350 	{
10351 		c2[0] = c[0] * r;
10352 		c2[1] = c[1] * g;
10353 		c2[2] = c[2] * b;
10354 		c2[3] = c[3] * a;
10355 	}
10356 }
10357 
RSurf_DrawBatch_GL11_ApplyAmbient(void)10358 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10359 {
10360 	int i;
10361 	const float *c;
10362 	float *c2;
10363 	if (!rsurface.passcolor4f)
10364 		return;
10365 	c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10366 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10367 	rsurface.passcolor4f_vertexbuffer = 0;
10368 	rsurface.passcolor4f_bufferoffset = 0;
10369 	for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10370 	{
10371 		c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10372 		c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10373 		c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10374 		c2[3] = c[3];
10375 	}
10376 }
10377 
RSurf_DrawBatch_GL11_Lightmap(float r,float g,float b,float a,qboolean applycolor,qboolean applyfog)10378 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10379 {
10380 	// TODO: optimize
10381 	rsurface.passcolor4f = NULL;
10382 	rsurface.passcolor4f_vertexbuffer = 0;
10383 	rsurface.passcolor4f_bufferoffset = 0;
10384 	if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10385 	if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10386 	R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10387 	GL_Color(r, g, b, a);
10388 	R_Mesh_TexBind(0, rsurface.lightmaptexture);
10389 	R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10390 	R_Mesh_TexMatrix(0, NULL);
10391 	RSurf_DrawBatch();
10392 }
10393 
RSurf_DrawBatch_GL11_Unlit(float r,float g,float b,float a,qboolean applycolor,qboolean applyfog)10394 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10395 {
10396 	// TODO: optimize applyfog && applycolor case
10397 	// just apply fog if necessary, and tint the fog color array if necessary
10398 	rsurface.passcolor4f = NULL;
10399 	rsurface.passcolor4f_vertexbuffer = 0;
10400 	rsurface.passcolor4f_bufferoffset = 0;
10401 	if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10402 	if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10403 	R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10404 	GL_Color(r, g, b, a);
10405 	RSurf_DrawBatch();
10406 }
10407 
RSurf_DrawBatch_GL11_VertexColor(float r,float g,float b,float a,qboolean applycolor,qboolean applyfog)10408 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10409 {
10410 	// TODO: optimize
10411 	rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10412 	rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10413 	rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10414 	if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10415 	if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10416 	R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10417 	GL_Color(r, g, b, a);
10418 	RSurf_DrawBatch();
10419 }
10420 
RSurf_DrawBatch_GL11_ClampColor(void)10421 static void RSurf_DrawBatch_GL11_ClampColor(void)
10422 {
10423 	int i;
10424 	const float *c1;
10425 	float *c2;
10426 	if (!rsurface.passcolor4f)
10427 		return;
10428 	for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10429 	{
10430 		c2[0] = bound(0.0f, c1[0], 1.0f);
10431 		c2[1] = bound(0.0f, c1[1], 1.0f);
10432 		c2[2] = bound(0.0f, c1[2], 1.0f);
10433 		c2[3] = bound(0.0f, c1[3], 1.0f);
10434 	}
10435 }
10436 
RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)10437 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10438 {
10439 	int i;
10440 	float f;
10441 	const float *v;
10442 	const float *n;
10443 	float *c;
10444 	//vec3_t eyedir;
10445 
10446 	// fake shading
10447 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10448 	rsurface.passcolor4f_vertexbuffer = 0;
10449 	rsurface.passcolor4f_bufferoffset = 0;
10450 	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)
10451 	{
10452 		f = -DotProduct(r_refdef.view.forward, n);
10453 		f = max(0, f);
10454 		f = f * 0.85 + 0.15; // work around so stuff won't get black
10455 		f *= fakelightintensity;
10456 		Vector4Set(c, f, f, f, 1);
10457 	}
10458 }
10459 
RSurf_DrawBatch_GL11_FakeLight(float r,float g,float b,float a,qboolean applycolor,qboolean applyfog)10460 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10461 {
10462 	RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10463 	if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10464 	if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10465 	R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10466 	GL_Color(r, g, b, a);
10467 	RSurf_DrawBatch();
10468 }
10469 
RSurf_DrawBatch_GL11_ApplyVertexShade(float * r,float * g,float * b,float * a,float lightmapintensity,qboolean * applycolor)10470 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10471 {
10472 	int i;
10473 	float f;
10474 	float alpha;
10475 	const float *v;
10476 	const float *n;
10477 	float *c;
10478 	vec3_t ambientcolor;
10479 	vec3_t diffusecolor;
10480 	vec3_t lightdir;
10481 	// TODO: optimize
10482 	// model lighting
10483 	VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10484 	f = 0.5f * lightmapintensity;
10485 	ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10486 	ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10487 	ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10488 	diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10489 	diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10490 	diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10491 	alpha = *a;
10492 	if (VectorLength2(diffusecolor) > 0)
10493 	{
10494 		// q3-style directional shading
10495 		rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10496 		rsurface.passcolor4f_vertexbuffer = 0;
10497 		rsurface.passcolor4f_bufferoffset = 0;
10498 		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)
10499 		{
10500 			if ((f = DotProduct(n, lightdir)) > 0)
10501 				VectorMA(ambientcolor, f, diffusecolor, c);
10502 			else
10503 				VectorCopy(ambientcolor, c);
10504 			c[3] = alpha;
10505 		}
10506 		*r = 1;
10507 		*g = 1;
10508 		*b = 1;
10509 		*a = 1;
10510 		*applycolor = false;
10511 	}
10512 	else
10513 	{
10514 		*r = ambientcolor[0];
10515 		*g = ambientcolor[1];
10516 		*b = ambientcolor[2];
10517 		rsurface.passcolor4f = NULL;
10518 		rsurface.passcolor4f_vertexbuffer = 0;
10519 		rsurface.passcolor4f_bufferoffset = 0;
10520 	}
10521 }
10522 
RSurf_DrawBatch_GL11_VertexShade(float r,float g,float b,float a,qboolean applycolor,qboolean applyfog)10523 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10524 {
10525 	RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
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 	RSurf_DrawBatch();
10531 }
10532 
RSurf_DrawBatch_GL11_MakeFogColor(float r,float g,float b,float a)10533 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10534 {
10535 	int i;
10536 	float f;
10537 	const float *v;
10538 	float *c;
10539 
10540 	// fake shading
10541 	rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10542 	rsurface.passcolor4f_vertexbuffer = 0;
10543 	rsurface.passcolor4f_bufferoffset = 0;
10544 
10545 	for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10546 	{
10547 		f = 1 - RSurf_FogVertex(v);
10548 		c[0] = r;
10549 		c[1] = g;
10550 		c[2] = b;
10551 		c[3] = f * a;
10552 	}
10553 }
10554 
RSurf_SetupDepthAndCulling(void)10555 void RSurf_SetupDepthAndCulling(void)
10556 {
10557 	// submodels are biased to avoid z-fighting with world surfaces that they
10558 	// may be exactly overlapping (avoids z-fighting artifacts on certain
10559 	// doors and things in Quake maps)
10560 	GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10561 	GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10562 	GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10563 	GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10564 }
10565 
R_DrawTextureSurfaceList_Sky(int texturenumsurfaces,const msurface_t ** texturesurfacelist)10566 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10567 {
10568 	int i, j;
10569 	// transparent sky would be ridiculous
10570 	if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10571 		return;
10572 	R_SetupShader_Generic_NoTexture(false, false);
10573 	skyrenderlater = true;
10574 	RSurf_SetupDepthAndCulling();
10575 	GL_DepthMask(true);
10576 
10577 	// add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10578 	if (r_sky_scissor.integer)
10579 	{
10580 		RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10581 		for (i = 0; i < texturenumsurfaces; i++)
10582 		{
10583 			const msurface_t *surf = texturesurfacelist[i];
10584 			const float *v;
10585 			float p[3];
10586 			float mins[3], maxs[3];
10587 			int scissor[4];
10588 			for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10589 			{
10590 				Matrix4x4_Transform(&rsurface.matrix, v, p);
10591 				if (j > 0)
10592 				{
10593 					if (mins[0] > p[0]) mins[0] = p[0];
10594 					if (mins[1] > p[1]) mins[1] = p[1];
10595 					if (mins[2] > p[2]) mins[2] = p[2];
10596 					if (maxs[0] < p[0]) maxs[0] = p[0];
10597 					if (maxs[1] < p[1]) maxs[1] = p[1];
10598 					if (maxs[2] < p[2]) maxs[2] = p[2];
10599 				}
10600 				else
10601 				{
10602 					VectorCopy(p, mins);
10603 					VectorCopy(p, maxs);
10604 				}
10605 			}
10606 			if (!R_ScissorForBBox(mins, maxs, scissor))
10607 			{
10608 				if (skyscissor[2])
10609 				{
10610 					if (skyscissor[0] > scissor[0])
10611 					{
10612 						skyscissor[2] += skyscissor[0] - scissor[0];
10613 						skyscissor[0] = scissor[0];
10614 					}
10615 					if (skyscissor[1] > scissor[1])
10616 					{
10617 						skyscissor[3] += skyscissor[1] - scissor[1];
10618 						skyscissor[1] = scissor[1];
10619 					}
10620 					if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10621 						skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10622 					if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10623 						skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10624 				}
10625 				else
10626 					Vector4Copy(scissor, skyscissor);
10627 			}
10628 		}
10629 	}
10630 
10631 	// LadyHavoc: HalfLife maps have freaky skypolys so don't use
10632 	// skymasking on them, and Quake3 never did sky masking (unlike
10633 	// software Quake and software Quake2), so disable the sky masking
10634 	// in Quake3 maps as it causes problems with q3map2 sky tricks,
10635 	// and skymasking also looks very bad when noclipping outside the
10636 	// level, so don't use it then either.
10637 	if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10638 	{
10639 		R_Mesh_ResetTextureState();
10640 		if (skyrendermasked)
10641 		{
10642 			R_SetupShader_DepthOrShadow(false, false, false);
10643 			// depth-only (masking)
10644 			GL_ColorMask(0, 0, 0, 0);
10645 			// just to make sure that braindead drivers don't draw
10646 			// anything despite that colormask...
10647 			GL_BlendFunc(GL_ZERO, GL_ONE);
10648 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10649 			R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10650 		}
10651 		else
10652 		{
10653 			R_SetupShader_Generic_NoTexture(false, false);
10654 			// fog sky
10655 			GL_BlendFunc(GL_ONE, GL_ZERO);
10656 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10657 			GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10658 			R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10659 		}
10660 		RSurf_DrawBatch();
10661 		if (skyrendermasked)
10662 			GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10663 	}
10664 	R_Mesh_ResetTextureState();
10665 	GL_Color(1, 1, 1, 1);
10666 }
10667 
10668 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10669 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
R_DrawTextureSurfaceList_GL20(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth,qboolean prepass)10670 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10671 {
10672 	if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10673 		return;
10674 	if (prepass)
10675 	{
10676 		// render screenspace normalmap to texture
10677 		GL_DepthMask(true);
10678 		R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10679 		RSurf_DrawBatch();
10680 		return;
10681 	}
10682 
10683 	// bind lightmap texture
10684 
10685 	// water/refraction/reflection/camera surfaces have to be handled specially
10686 	if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10687 	{
10688 		int start, end, startplaneindex;
10689 		for (start = 0;start < texturenumsurfaces;start = end)
10690 		{
10691 			startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10692 			if(startplaneindex < 0)
10693 			{
10694 				// this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10695 				// Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10696 				end = start + 1;
10697 				continue;
10698 			}
10699 			for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10700 				;
10701 			// now that we have a batch using the same planeindex, render it
10702 			if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10703 			{
10704 				// render water or distortion background
10705 				GL_DepthMask(true);
10706 				R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10707 				RSurf_DrawBatch();
10708 				// blend surface on top
10709 				GL_DepthMask(false);
10710 				R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10711 				RSurf_DrawBatch();
10712 			}
10713 			else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10714 			{
10715 				// render surface with reflection texture as input
10716 				GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10717 				R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10718 				RSurf_DrawBatch();
10719 			}
10720 		}
10721 		return;
10722 	}
10723 
10724 	// render surface batch normally
10725 	GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10726 	R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10727 	RSurf_DrawBatch();
10728 }
10729 
R_DrawTextureSurfaceList_GL13(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth)10730 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10731 {
10732 	// OpenGL 1.3 path - anything not completely ancient
10733 	qboolean applycolor;
10734 	qboolean applyfog;
10735 	int layerindex;
10736 	const texturelayer_t *layer;
10737 	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10738 	R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10739 
10740 	for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10741 	{
10742 		vec4_t layercolor;
10743 		int layertexrgbscale;
10744 		if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10745 		{
10746 			if (layerindex == 0)
10747 				GL_AlphaTest(true);
10748 			else
10749 			{
10750 				GL_AlphaTest(false);
10751 				GL_DepthFunc(GL_EQUAL);
10752 			}
10753 		}
10754 		GL_DepthMask(layer->depthmask && writedepth);
10755 		GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10756 		if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10757 		{
10758 			layertexrgbscale = 4;
10759 			VectorScale(layer->color, 0.25f, layercolor);
10760 		}
10761 		else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10762 		{
10763 			layertexrgbscale = 2;
10764 			VectorScale(layer->color, 0.5f, layercolor);
10765 		}
10766 		else
10767 		{
10768 			layertexrgbscale = 1;
10769 			VectorScale(layer->color, 1.0f, layercolor);
10770 		}
10771 		layercolor[3] = layer->color[3];
10772 		applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10773 		R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10774 		applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10775 		switch (layer->type)
10776 		{
10777 		case TEXTURELAYERTYPE_LITTEXTURE:
10778 			// single-pass lightmapped texture with 2x rgbscale
10779 			R_Mesh_TexBind(0, r_texture_white);
10780 			R_Mesh_TexMatrix(0, NULL);
10781 			R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10782 			R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10783 			R_Mesh_TexBind(1, layer->texture);
10784 			R_Mesh_TexMatrix(1, &layer->texmatrix);
10785 			R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10786 			R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10787 			if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10788 				RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10789 			else if (FAKELIGHT_ENABLED)
10790 				RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10791 			else if (rsurface.uselightmaptexture)
10792 				RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10793 			else
10794 				RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10795 			break;
10796 		case TEXTURELAYERTYPE_TEXTURE:
10797 			// singletexture unlit texture with transparency support
10798 			R_Mesh_TexBind(0, layer->texture);
10799 			R_Mesh_TexMatrix(0, &layer->texmatrix);
10800 			R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10801 			R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10802 			R_Mesh_TexBind(1, 0);
10803 			R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10804 			RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10805 			break;
10806 		case TEXTURELAYERTYPE_FOG:
10807 			// singletexture fogging
10808 			if (layer->texture)
10809 			{
10810 				R_Mesh_TexBind(0, layer->texture);
10811 				R_Mesh_TexMatrix(0, &layer->texmatrix);
10812 				R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10814 			}
10815 			else
10816 			{
10817 				R_Mesh_TexBind(0, 0);
10818 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10819 			}
10820 			R_Mesh_TexBind(1, 0);
10821 			R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10822 			// generate a color array for the fog pass
10823 			RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10824 			R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10825 			RSurf_DrawBatch();
10826 			break;
10827 		default:
10828 			Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10829 		}
10830 	}
10831 	if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10832 	{
10833 		GL_DepthFunc(GL_LEQUAL);
10834 		GL_AlphaTest(false);
10835 	}
10836 }
10837 
R_DrawTextureSurfaceList_GL11(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth)10838 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10839 {
10840 	// OpenGL 1.1 - crusty old voodoo path
10841 	qboolean applyfog;
10842 	int layerindex;
10843 	const texturelayer_t *layer;
10844 	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10845 	R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10846 
10847 	for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10848 	{
10849 		if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10850 		{
10851 			if (layerindex == 0)
10852 				GL_AlphaTest(true);
10853 			else
10854 			{
10855 				GL_AlphaTest(false);
10856 				GL_DepthFunc(GL_EQUAL);
10857 			}
10858 		}
10859 		GL_DepthMask(layer->depthmask && writedepth);
10860 		GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10861 		R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10862 		applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10863 		switch (layer->type)
10864 		{
10865 		case TEXTURELAYERTYPE_LITTEXTURE:
10866 			if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10867 			{
10868 				// two-pass lit texture with 2x rgbscale
10869 				// first the lightmap pass
10870 				R_Mesh_TexBind(0, r_texture_white);
10871 				R_Mesh_TexMatrix(0, NULL);
10872 				R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10873 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10874 				if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10875 					RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10876 				else if (FAKELIGHT_ENABLED)
10877 					RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10878 				else if (rsurface.uselightmaptexture)
10879 					RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10880 				else
10881 					RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10882 				// then apply the texture to it
10883 				GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10884 				R_Mesh_TexBind(0, layer->texture);
10885 				R_Mesh_TexMatrix(0, &layer->texmatrix);
10886 				R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10887 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10888 				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);
10889 			}
10890 			else
10891 			{
10892 				// single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10893 				R_Mesh_TexBind(0, layer->texture);
10894 				R_Mesh_TexMatrix(0, &layer->texmatrix);
10895 				R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10896 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10897 				if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10898 					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);
10899 				else if (FAKELIGHT_ENABLED)
10900 					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);
10901 				else
10902 					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);
10903 			}
10904 			break;
10905 		case TEXTURELAYERTYPE_TEXTURE:
10906 			// singletexture unlit texture with transparency support
10907 			R_Mesh_TexBind(0, layer->texture);
10908 			R_Mesh_TexMatrix(0, &layer->texmatrix);
10909 			R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10910 			R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10911 			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);
10912 			break;
10913 		case TEXTURELAYERTYPE_FOG:
10914 			// singletexture fogging
10915 			if (layer->texture)
10916 			{
10917 				R_Mesh_TexBind(0, layer->texture);
10918 				R_Mesh_TexMatrix(0, &layer->texmatrix);
10919 				R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10920 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10921 			}
10922 			else
10923 			{
10924 				R_Mesh_TexBind(0, 0);
10925 				R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10926 			}
10927 			// generate a color array for the fog pass
10928 			RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10929 			R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10930 			RSurf_DrawBatch();
10931 			break;
10932 		default:
10933 			Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10934 		}
10935 	}
10936 	if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10937 	{
10938 		GL_DepthFunc(GL_LEQUAL);
10939 		GL_AlphaTest(false);
10940 	}
10941 }
10942 
R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth)10943 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10944 {
10945 	int vi;
10946 	int j;
10947 	r_vertexgeneric_t *batchvertex;
10948 	float c[4];
10949 	texture_t *t = rsurface.texture;
10950 
10951 //	R_Mesh_ResetTextureState();
10952 	R_SetupShader_Generic_NoTexture(false, false);
10953 
10954 	if(t && t->currentskinframe)
10955 	{
10956 		memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10957 		c[3] *= t->currentalpha;
10958 	}
10959 	else
10960 	{
10961 		c[0] = 1;
10962 		c[1] = 0;
10963 		c[2] = 1;
10964 		c[3] = 1;
10965 	}
10966 
10967 	if (t->pantstexture || t->shirttexture)
10968 	{
10969 		c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10970 		c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10971 		c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10972 	}
10973 
10974 	// brighten it up (as texture value 127 means "unlit")
10975 	c[0] *= 2 * r_refdef.view.colorscale;
10976 	c[1] *= 2 * r_refdef.view.colorscale;
10977 	c[2] *= 2 * r_refdef.view.colorscale;
10978 
10979 	if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10980 		c[3] *= r_wateralpha.value;
10981 
10982 	if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10983 	{
10984 		GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10985 		GL_DepthMask(false);
10986 	}
10987 	else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10988 	{
10989 		GL_BlendFunc(GL_ONE, GL_ONE);
10990 		GL_DepthMask(false);
10991 	}
10992 	else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10993 	{
10994 		GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10995 		GL_DepthMask(false);
10996 	}
10997 	else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10998 	{
10999 		GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11000 		GL_DepthMask(false);
11001 	}
11002 	else
11003 	{
11004 		GL_BlendFunc(GL_ONE, GL_ZERO);
11005 		GL_DepthMask(writedepth);
11006 	}
11007 
11008 	if (r_showsurfaces.integer == 3)
11009 	{
11010 		rsurface.passcolor4f = NULL;
11011 
11012 		if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11013 		{
11014 			qboolean applycolor = true;
11015 			float one = 1.0;
11016 
11017 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11018 
11019 			RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11020 		}
11021 		else if (FAKELIGHT_ENABLED)
11022 		{
11023 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024 
11025 			RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11026 		}
11027 		else
11028 		{
11029 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11030 
11031 			rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11032 			rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11033 			rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11034 			RSurf_DrawBatch_GL11_ApplyAmbient();
11035 		}
11036 
11037 		if(!rsurface.passcolor4f)
11038 			RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11039 
11040 		RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11041 		if(r_refdef.fogenabled)
11042 			RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11043 		RSurf_DrawBatch_GL11_ClampColor();
11044 
11045 		R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11046 		R_SetupShader_Generic_NoTexture(false, false);
11047 		RSurf_DrawBatch();
11048 	}
11049 	else if (!r_refdef.view.showdebug)
11050 	{
11051 		RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052 		batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11053 		for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11054 		{
11055 			VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11056 			Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11057 		}
11058 		R_Mesh_PrepareVertices_Generic_Unlock();
11059 		RSurf_DrawBatch();
11060 	}
11061 	else if (r_showsurfaces.integer == 4)
11062 	{
11063 		RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064 		batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11065 		for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11066 		{
11067 			unsigned char d = (vi << 3) * (1.0f / 256.0f);
11068 			VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11069 			Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11070 		}
11071 		R_Mesh_PrepareVertices_Generic_Unlock();
11072 		RSurf_DrawBatch();
11073 	}
11074 	else if (r_showsurfaces.integer == 2)
11075 	{
11076 		const int *e;
11077 		RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078 		batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11079 		for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11080 		{
11081 			unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11082 			VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11083 			VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11084 			VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11085 			Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11086 			Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11087 			Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11088 		}
11089 		R_Mesh_PrepareVertices_Generic_Unlock();
11090 		R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11091 	}
11092 	else
11093 	{
11094 		int texturesurfaceindex;
11095 		int k;
11096 		const msurface_t *surface;
11097 		float surfacecolor4f[4];
11098 		RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099 		batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11100 		vi = 0;
11101 		for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11102 		{
11103 			surface = texturesurfacelist[texturesurfaceindex];
11104 			k = (int)(((size_t)surface) / sizeof(msurface_t));
11105 			Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11106 			for (j = 0;j < surface->num_vertices;j++)
11107 			{
11108 				VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11109 				Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11110 				vi++;
11111 			}
11112 		}
11113 		R_Mesh_PrepareVertices_Generic_Unlock();
11114 		RSurf_DrawBatch();
11115 	}
11116 }
11117 
R_DrawModelTextureSurfaceList(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth,qboolean prepass)11118 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11119 {
11120 	CHECKGLERROR
11121 	RSurf_SetupDepthAndCulling();
11122 	if (r_showsurfaces.integer)
11123 	{
11124 		R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11125 		return;
11126 	}
11127 	switch (vid.renderpath)
11128 	{
11129 	case RENDERPATH_GL20:
11130 	case RENDERPATH_D3D9:
11131 	case RENDERPATH_D3D10:
11132 	case RENDERPATH_D3D11:
11133 	case RENDERPATH_SOFT:
11134 	case RENDERPATH_GLES2:
11135 		R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11136 		break;
11137 	case RENDERPATH_GL13:
11138 	case RENDERPATH_GLES1:
11139 		R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11140 		break;
11141 	case RENDERPATH_GL11:
11142 		R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11143 		break;
11144 	}
11145 	CHECKGLERROR
11146 }
11147 
R_DrawSurface_TransparentCallback(const entity_render_t * ent,const rtlight_t * rtlight,int numsurfaces,int * surfacelist)11148 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11149 {
11150 	int i, j;
11151 	int texturenumsurfaces, endsurface;
11152 	texture_t *texture;
11153 	const msurface_t *surface;
11154 	const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11155 
11156 	if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11157 		RSurf_ActiveModelEntity(ent, false, false, false);
11158 	else
11159 	{
11160 		switch (vid.renderpath)
11161 		{
11162 		case RENDERPATH_GL20:
11163 		case RENDERPATH_D3D9:
11164 		case RENDERPATH_D3D10:
11165 		case RENDERPATH_D3D11:
11166 		case RENDERPATH_SOFT:
11167 		case RENDERPATH_GLES2:
11168 			RSurf_ActiveModelEntity(ent, true, true, false);
11169 			break;
11170 		case RENDERPATH_GL11:
11171 		case RENDERPATH_GL13:
11172 		case RENDERPATH_GLES1:
11173 			RSurf_ActiveModelEntity(ent, true, false, false);
11174 			break;
11175 		}
11176 	}
11177 
11178 	if (r_transparentdepthmasking.integer)
11179 	{
11180 		qboolean setup = false;
11181 		for (i = 0;i < numsurfaces;i = j)
11182 		{
11183 			j = i + 1;
11184 			surface = rsurface.modelsurfaces + surfacelist[i];
11185 			texture = surface->texture;
11186 			rsurface.texture = R_GetCurrentTexture(texture);
11187 			rsurface.lightmaptexture = NULL;
11188 			rsurface.deluxemaptexture = NULL;
11189 			rsurface.uselightmaptexture = false;
11190 			// scan ahead until we find a different texture
11191 			endsurface = min(i + 1024, numsurfaces);
11192 			texturenumsurfaces = 0;
11193 			texturesurfacelist[texturenumsurfaces++] = surface;
11194 			for (;j < endsurface;j++)
11195 			{
11196 				surface = rsurface.modelsurfaces + surfacelist[j];
11197 				if (texture != surface->texture)
11198 					break;
11199 				texturesurfacelist[texturenumsurfaces++] = surface;
11200 			}
11201 			if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11202 				continue;
11203 			// render the range of surfaces as depth
11204 			if (!setup)
11205 			{
11206 				setup = true;
11207 				GL_ColorMask(0,0,0,0);
11208 				GL_Color(1,1,1,1);
11209 				GL_DepthTest(true);
11210 				GL_BlendFunc(GL_ONE, GL_ZERO);
11211 				GL_DepthMask(true);
11212 //				R_Mesh_ResetTextureState();
11213 			}
11214 			RSurf_SetupDepthAndCulling();
11215 			RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11216 			R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11217 			R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11218 			RSurf_DrawBatch();
11219 		}
11220 		if (setup)
11221 			GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11222 	}
11223 
11224 	for (i = 0;i < numsurfaces;i = j)
11225 	{
11226 		j = i + 1;
11227 		surface = rsurface.modelsurfaces + surfacelist[i];
11228 		texture = surface->texture;
11229 		rsurface.texture = R_GetCurrentTexture(texture);
11230 		// scan ahead until we find a different texture
11231 		endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11232 		texturenumsurfaces = 0;
11233 		texturesurfacelist[texturenumsurfaces++] = surface;
11234 		if(FAKELIGHT_ENABLED)
11235 		{
11236 			rsurface.lightmaptexture = NULL;
11237 			rsurface.deluxemaptexture = NULL;
11238 			rsurface.uselightmaptexture = false;
11239 			for (;j < endsurface;j++)
11240 			{
11241 				surface = rsurface.modelsurfaces + surfacelist[j];
11242 				if (texture != surface->texture)
11243 					break;
11244 				texturesurfacelist[texturenumsurfaces++] = surface;
11245 			}
11246 		}
11247 		else
11248 		{
11249 			rsurface.lightmaptexture = surface->lightmaptexture;
11250 			rsurface.deluxemaptexture = surface->deluxemaptexture;
11251 			rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11252 			for (;j < endsurface;j++)
11253 			{
11254 				surface = rsurface.modelsurfaces + surfacelist[j];
11255 				if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11256 					break;
11257 				texturesurfacelist[texturenumsurfaces++] = surface;
11258 			}
11259 		}
11260 		// render the range of surfaces
11261 		R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11262 	}
11263 	rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11264 }
11265 
R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces,const msurface_t ** texturesurfacelist)11266 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11267 {
11268 	// transparent surfaces get pushed off into the transparent queue
11269 	int surfacelistindex;
11270 	const msurface_t *surface;
11271 	vec3_t tempcenter, center;
11272 	for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11273 	{
11274 		surface = texturesurfacelist[surfacelistindex];
11275 		if (r_transparent_sortsurfacesbynearest.integer)
11276 		{
11277 			tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11278 			tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11279 			tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11280 		}
11281 		else
11282 		{
11283 			tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11284 			tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11285 			tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11286 		}
11287 		Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11288 		if (rsurface.entity->transparent_offset) // transparent offset
11289 		{
11290 			center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11291 			center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11292 			center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11293 		}
11294 		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);
11295 	}
11296 }
11297 
R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces,const msurface_t ** texturesurfacelist)11298 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11299 {
11300 	if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11301 		return;
11302 	if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11303 		return;
11304 	RSurf_SetupDepthAndCulling();
11305 	RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11306 	R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11307 	R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11308 	RSurf_DrawBatch();
11309 }
11310 
R_ProcessModelTextureSurfaceList(int texturenumsurfaces,const msurface_t ** texturesurfacelist,qboolean writedepth,qboolean depthonly,qboolean prepass)11311 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11312 {
11313 	CHECKGLERROR
11314 	if (depthonly)
11315 		R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11316 	else if (prepass)
11317 	{
11318 		if (!rsurface.texture->currentnumlayers)
11319 			return;
11320 		if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11321 			R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11322 		else
11323 			R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11324 	}
11325 	else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11326 		R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11327 	else if (!rsurface.texture->currentnumlayers)
11328 		return;
11329 	else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11330 	{
11331 		// in the deferred case, transparent surfaces were queued during prepass
11332 		if (!r_shadow_usingdeferredprepass)
11333 			R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11334 	}
11335 	else
11336 	{
11337 		// the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11338 		R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11339 	}
11340 	CHECKGLERROR
11341 }
11342 
R_QueueModelSurfaceList(entity_render_t * ent,int numsurfaces,const msurface_t ** surfacelist,int flagsmask,qboolean writedepth,qboolean depthonly,qboolean prepass)11343 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11344 {
11345 	int i, j;
11346 	texture_t *texture;
11347 	R_FrameData_SetMark();
11348 	// break the surface list down into batches by texture and use of lightmapping
11349 	for (i = 0;i < numsurfaces;i = j)
11350 	{
11351 		j = i + 1;
11352 		// texture is the base texture pointer, rsurface.texture is the
11353 		// current frame/skin the texture is directing us to use (for example
11354 		// if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11355 		// use skin 1 instead)
11356 		texture = surfacelist[i]->texture;
11357 		rsurface.texture = R_GetCurrentTexture(texture);
11358 		if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11359 		{
11360 			// if this texture is not the kind we want, skip ahead to the next one
11361 			for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11362 				;
11363 			continue;
11364 		}
11365 		if(FAKELIGHT_ENABLED || depthonly || prepass)
11366 		{
11367 			rsurface.lightmaptexture = NULL;
11368 			rsurface.deluxemaptexture = NULL;
11369 			rsurface.uselightmaptexture = false;
11370 			// simply scan ahead until we find a different texture or lightmap state
11371 			for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11372 				;
11373 		}
11374 		else
11375 		{
11376 			rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11377 			rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11378 			rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11379 			// simply scan ahead until we find a different texture or lightmap state
11380 			for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11381 				;
11382 		}
11383 		// render the range of surfaces
11384 		R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11385 	}
11386 	R_FrameData_ReturnToMark();
11387 }
11388 
11389 float locboxvertex3f[6*4*3] =
11390 {
11391 	1,0,1, 1,0,0, 1,1,0, 1,1,1,
11392 	0,1,1, 0,1,0, 0,0,0, 0,0,1,
11393 	1,1,1, 1,1,0, 0,1,0, 0,1,1,
11394 	0,0,1, 0,0,0, 1,0,0, 1,0,1,
11395 	0,0,1, 1,0,1, 1,1,1, 0,1,1,
11396 	1,0,0, 0,0,0, 0,1,0, 1,1,0
11397 };
11398 
11399 unsigned short locboxelements[6*2*3] =
11400 {
11401 	 0, 1, 2, 0, 2, 3,
11402 	 4, 5, 6, 4, 6, 7,
11403 	 8, 9,10, 8,10,11,
11404 	12,13,14, 12,14,15,
11405 	16,17,18, 16,18,19,
11406 	20,21,22, 20,22,23
11407 };
11408 
R_DrawLoc_Callback(const entity_render_t * ent,const rtlight_t * rtlight,int numsurfaces,int * surfacelist)11409 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11410 {
11411 	int i, j;
11412 	cl_locnode_t *loc = (cl_locnode_t *)ent;
11413 	vec3_t mins, size;
11414 	float vertex3f[6*4*3];
11415 	CHECKGLERROR
11416 	GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417 	GL_DepthMask(false);
11418 	GL_DepthRange(0, 1);
11419 	GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11420 	GL_DepthTest(true);
11421 	GL_CullFace(GL_NONE);
11422 	R_EntityMatrix(&identitymatrix);
11423 
11424 //	R_Mesh_ResetTextureState();
11425 
11426 	i = surfacelist[0];
11427 	GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11428 			 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11429 			 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11430 			surfacelist[0] < 0 ? 0.5f : 0.125f);
11431 
11432 	if (VectorCompare(loc->mins, loc->maxs))
11433 	{
11434 		VectorSet(size, 2, 2, 2);
11435 		VectorMA(loc->mins, -0.5f, size, mins);
11436 	}
11437 	else
11438 	{
11439 		VectorCopy(loc->mins, mins);
11440 		VectorSubtract(loc->maxs, loc->mins, size);
11441 	}
11442 
11443 	for (i = 0;i < 6*4*3;)
11444 		for (j = 0;j < 3;j++, i++)
11445 			vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11446 
11447 	R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11448 	R_SetupShader_Generic_NoTexture(false, false);
11449 	R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11450 }
11451 
R_DrawLocs(void)11452 void R_DrawLocs(void)
11453 {
11454 	int index;
11455 	cl_locnode_t *loc, *nearestloc;
11456 	vec3_t center;
11457 	nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11458 	for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11459 	{
11460 		VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11461 		R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11462 	}
11463 }
11464 
R_DecalSystem_Reset(decalsystem_t * decalsystem)11465 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11466 {
11467 	if (decalsystem->decals)
11468 		Mem_Free(decalsystem->decals);
11469 	memset(decalsystem, 0, sizeof(*decalsystem));
11470 }
11471 
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)11472 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)
11473 {
11474 	tridecal_t *decal;
11475 	tridecal_t *decals;
11476 	int i;
11477 
11478 	// expand or initialize the system
11479 	if (decalsystem->maxdecals <= decalsystem->numdecals)
11480 	{
11481 		decalsystem_t old = *decalsystem;
11482 		qboolean useshortelements;
11483 		decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11484 		useshortelements = decalsystem->maxdecals * 3 <= 65536;
11485 		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)));
11486 		decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11487 		decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11488 		decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11489 		decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11490 		decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11491 		if (decalsystem->numdecals)
11492 			memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11493 		if (old.decals)
11494 			Mem_Free(old.decals);
11495 		for (i = 0;i < decalsystem->maxdecals*3;i++)
11496 			decalsystem->element3i[i] = i;
11497 		if (useshortelements)
11498 			for (i = 0;i < decalsystem->maxdecals*3;i++)
11499 				decalsystem->element3s[i] = i;
11500 	}
11501 
11502 	// grab a decal and search for another free slot for the next one
11503 	decals = decalsystem->decals;
11504 	decal = decalsystem->decals + (i = decalsystem->freedecal++);
11505 	for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11506 		;
11507 	decalsystem->freedecal = i;
11508 	if (decalsystem->numdecals <= i)
11509 		decalsystem->numdecals = i + 1;
11510 
11511 	// initialize the decal
11512 	decal->lived = 0;
11513 	decal->triangleindex = triangleindex;
11514 	decal->surfaceindex = surfaceindex;
11515 	decal->decalsequence = decalsequence;
11516 	decal->color4f[0][0] = c0[0];
11517 	decal->color4f[0][1] = c0[1];
11518 	decal->color4f[0][2] = c0[2];
11519 	decal->color4f[0][3] = 1;
11520 	decal->color4f[1][0] = c1[0];
11521 	decal->color4f[1][1] = c1[1];
11522 	decal->color4f[1][2] = c1[2];
11523 	decal->color4f[1][3] = 1;
11524 	decal->color4f[2][0] = c2[0];
11525 	decal->color4f[2][1] = c2[1];
11526 	decal->color4f[2][2] = c2[2];
11527 	decal->color4f[2][3] = 1;
11528 	decal->vertex3f[0][0] = v0[0];
11529 	decal->vertex3f[0][1] = v0[1];
11530 	decal->vertex3f[0][2] = v0[2];
11531 	decal->vertex3f[1][0] = v1[0];
11532 	decal->vertex3f[1][1] = v1[1];
11533 	decal->vertex3f[1][2] = v1[2];
11534 	decal->vertex3f[2][0] = v2[0];
11535 	decal->vertex3f[2][1] = v2[1];
11536 	decal->vertex3f[2][2] = v2[2];
11537 	decal->texcoord2f[0][0] = t0[0];
11538 	decal->texcoord2f[0][1] = t0[1];
11539 	decal->texcoord2f[1][0] = t1[0];
11540 	decal->texcoord2f[1][1] = t1[1];
11541 	decal->texcoord2f[2][0] = t2[0];
11542 	decal->texcoord2f[2][1] = t2[1];
11543 	TriangleNormal(v0, v1, v2, decal->plane);
11544 	VectorNormalize(decal->plane);
11545 	decal->plane[3] = DotProduct(v0, decal->plane);
11546 }
11547 
11548 extern cvar_t cl_decals_bias;
11549 extern cvar_t cl_decals_models;
11550 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11551 // baseparms, parms, temps
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)11552 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)
11553 {
11554 	int cornerindex;
11555 	int index;
11556 	float v[9][3];
11557 	const float *vertex3f;
11558 	const float *normal3f;
11559 	int numpoints;
11560 	float points[2][9][3];
11561 	float temp[3];
11562 	float tc[9][2];
11563 	float f;
11564 	float c[9][4];
11565 	const int *e;
11566 
11567 	e = rsurface.modelelement3i + 3*triangleindex;
11568 
11569 	vertex3f = rsurface.modelvertex3f;
11570 	normal3f = rsurface.modelnormal3f;
11571 
11572 	if (normal3f)
11573 	{
11574 		for (cornerindex = 0;cornerindex < 3;cornerindex++)
11575 		{
11576 			index = 3*e[cornerindex];
11577 			VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11578 		}
11579 	}
11580 	else
11581 	{
11582 		for (cornerindex = 0;cornerindex < 3;cornerindex++)
11583 		{
11584 			index = 3*e[cornerindex];
11585 			VectorCopy(vertex3f + index, v[cornerindex]);
11586 		}
11587 	}
11588 
11589 	// cull backfaces
11590 	//TriangleNormal(v[0], v[1], v[2], normal);
11591 	//if (DotProduct(normal, localnormal) < 0.0f)
11592 	//	continue;
11593 	// clip by each of the box planes formed from the projection matrix
11594 	// if anything survives, we emit the decal
11595 	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]);
11596 	if (numpoints < 3)
11597 		return;
11598 	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]);
11599 	if (numpoints < 3)
11600 		return;
11601 	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]);
11602 	if (numpoints < 3)
11603 		return;
11604 	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]);
11605 	if (numpoints < 3)
11606 		return;
11607 	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]);
11608 	if (numpoints < 3)
11609 		return;
11610 	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]);
11611 	if (numpoints < 3)
11612 		return;
11613 	// some part of the triangle survived, so we have to accept it...
11614 	if (dynamic)
11615 	{
11616 		// dynamic always uses the original triangle
11617 		numpoints = 3;
11618 		for (cornerindex = 0;cornerindex < 3;cornerindex++)
11619 		{
11620 			index = 3*e[cornerindex];
11621 			VectorCopy(vertex3f + index, v[cornerindex]);
11622 		}
11623 	}
11624 	for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11625 	{
11626 		// convert vertex positions to texcoords
11627 		Matrix4x4_Transform(projection, v[cornerindex], temp);
11628 		tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11629 		tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11630 		// calculate distance fade from the projection origin
11631 		f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11632 		f = bound(0.0f, f, 1.0f);
11633 		c[cornerindex][0] = r * f;
11634 		c[cornerindex][1] = g * f;
11635 		c[cornerindex][2] = b * f;
11636 		c[cornerindex][3] = 1.0f;
11637 		//VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11638 	}
11639 	if (dynamic)
11640 		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);
11641 	else
11642 		for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11643 			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);
11644 }
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)11645 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)
11646 {
11647 	matrix4x4_t projection;
11648 	decalsystem_t *decalsystem;
11649 	qboolean dynamic;
11650 	dp_model_t *model;
11651 	const msurface_t *surface;
11652 	const msurface_t *surfaces;
11653 	const int *surfacelist;
11654 	const texture_t *texture;
11655 	int numtriangles;
11656 	int numsurfacelist;
11657 	int surfacelistindex;
11658 	int surfaceindex;
11659 	int triangleindex;
11660 	float localorigin[3];
11661 	float localnormal[3];
11662 	float localmins[3];
11663 	float localmaxs[3];
11664 	float localsize;
11665 	//float normal[3];
11666 	float planes[6][4];
11667 	float angles[3];
11668 	bih_t *bih;
11669 	int bih_triangles_count;
11670 	int bih_triangles[256];
11671 	int bih_surfaces[256];
11672 
11673 	decalsystem = &ent->decalsystem;
11674 	model = ent->model;
11675 	if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11676 	{
11677 		R_DecalSystem_Reset(&ent->decalsystem);
11678 		return;
11679 	}
11680 
11681 	if (!model->brush.data_leafs && !cl_decals_models.integer)
11682 	{
11683 		if (decalsystem->model)
11684 			R_DecalSystem_Reset(decalsystem);
11685 		return;
11686 	}
11687 
11688 	if (decalsystem->model != model)
11689 		R_DecalSystem_Reset(decalsystem);
11690 	decalsystem->model = model;
11691 
11692 	RSurf_ActiveModelEntity(ent, true, false, false);
11693 
11694 	Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11695 	Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11696 	VectorNormalize(localnormal);
11697 	localsize = worldsize*rsurface.inversematrixscale;
11698 	localmins[0] = localorigin[0] - localsize;
11699 	localmins[1] = localorigin[1] - localsize;
11700 	localmins[2] = localorigin[2] - localsize;
11701 	localmaxs[0] = localorigin[0] + localsize;
11702 	localmaxs[1] = localorigin[1] + localsize;
11703 	localmaxs[2] = localorigin[2] + localsize;
11704 
11705 	//VectorCopy(localnormal, planes[4]);
11706 	//VectorVectors(planes[4], planes[2], planes[0]);
11707 	AnglesFromVectors(angles, localnormal, NULL, false);
11708 	AngleVectors(angles, planes[0], planes[2], planes[4]);
11709 	VectorNegate(planes[0], planes[1]);
11710 	VectorNegate(planes[2], planes[3]);
11711 	VectorNegate(planes[4], planes[5]);
11712 	planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11713 	planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11714 	planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11715 	planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11716 	planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11717 	planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11718 
11719 #if 1
11720 // works
11721 {
11722 	matrix4x4_t forwardprojection;
11723 	Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11724 	Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11725 }
11726 #else
11727 // broken
11728 {
11729 	float projectionvector[4][3];
11730 	VectorScale(planes[0], ilocalsize, projectionvector[0]);
11731 	VectorScale(planes[2], ilocalsize, projectionvector[1]);
11732 	VectorScale(planes[4], ilocalsize, projectionvector[2]);
11733 	projectionvector[0][0] = planes[0][0] * ilocalsize;
11734 	projectionvector[0][1] = planes[1][0] * ilocalsize;
11735 	projectionvector[0][2] = planes[2][0] * ilocalsize;
11736 	projectionvector[1][0] = planes[0][1] * ilocalsize;
11737 	projectionvector[1][1] = planes[1][1] * ilocalsize;
11738 	projectionvector[1][2] = planes[2][1] * ilocalsize;
11739 	projectionvector[2][0] = planes[0][2] * ilocalsize;
11740 	projectionvector[2][1] = planes[1][2] * ilocalsize;
11741 	projectionvector[2][2] = planes[2][2] * ilocalsize;
11742 	projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11743 	projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11744 	projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11745 	Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11746 }
11747 #endif
11748 
11749 	dynamic = model->surfmesh.isanimated;
11750 	numsurfacelist = model->nummodelsurfaces;
11751 	surfacelist = model->sortedmodelsurfaces;
11752 	surfaces = model->data_surfaces;
11753 
11754 	bih = NULL;
11755 	bih_triangles_count = -1;
11756 	if(!dynamic)
11757 	{
11758 		if(model->render_bih.numleafs)
11759 			bih = &model->render_bih;
11760 		else if(model->collision_bih.numleafs)
11761 			bih = &model->collision_bih;
11762 	}
11763 	if(bih)
11764 		bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11765 	if(bih_triangles_count == 0)
11766 		return;
11767 	if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11768 		return;
11769 	if(bih_triangles_count > 0)
11770 	{
11771 		for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11772 		{
11773 			surfaceindex = bih_surfaces[triangleindex];
11774 			surface = surfaces + surfaceindex;
11775 			texture = surface->texture;
11776 			if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11777 				continue;
11778 			if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11779 				continue;
11780 			R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11781 		}
11782 	}
11783 	else
11784 	{
11785 		for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11786 		{
11787 			surfaceindex = surfacelist[surfacelistindex];
11788 			surface = surfaces + surfaceindex;
11789 			// check cull box first because it rejects more than any other check
11790 			if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11791 				continue;
11792 			// skip transparent surfaces
11793 			texture = surface->texture;
11794 			if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11795 				continue;
11796 			if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11797 				continue;
11798 			numtriangles = surface->num_triangles;
11799 			for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11800 				R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11801 		}
11802 	}
11803 }
11804 
11805 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
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)11806 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)
11807 {
11808 	int renderentityindex;
11809 	float worldmins[3];
11810 	float worldmaxs[3];
11811 	entity_render_t *ent;
11812 
11813 	if (!cl_decals_newsystem.integer)
11814 		return;
11815 
11816 	worldmins[0] = worldorigin[0] - worldsize;
11817 	worldmins[1] = worldorigin[1] - worldsize;
11818 	worldmins[2] = worldorigin[2] - worldsize;
11819 	worldmaxs[0] = worldorigin[0] + worldsize;
11820 	worldmaxs[1] = worldorigin[1] + worldsize;
11821 	worldmaxs[2] = worldorigin[2] + worldsize;
11822 
11823 	R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11824 
11825 	for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11826 	{
11827 		ent = r_refdef.scene.entities[renderentityindex];
11828 		if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11829 			continue;
11830 
11831 		R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11832 	}
11833 }
11834 
11835 typedef struct r_decalsystem_splatqueue_s
11836 {
11837 	vec3_t worldorigin;
11838 	vec3_t worldnormal;
11839 	float color[4];
11840 	float tcrange[4];
11841 	float worldsize;
11842 	unsigned int decalsequence;
11843 }
11844 r_decalsystem_splatqueue_t;
11845 
11846 int r_decalsystem_numqueued = 0;
11847 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11848 
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)11849 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)
11850 {
11851 	r_decalsystem_splatqueue_t *queue;
11852 
11853 	if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11854 		return;
11855 
11856 	queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11857 	VectorCopy(worldorigin, queue->worldorigin);
11858 	VectorCopy(worldnormal, queue->worldnormal);
11859 	Vector4Set(queue->color, r, g, b, a);
11860 	Vector4Set(queue->tcrange, s1, t1, s2, t2);
11861 	queue->worldsize = worldsize;
11862 	queue->decalsequence = cl.decalsequence++;
11863 }
11864 
R_DecalSystem_ApplySplatEntitiesQueue(void)11865 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11866 {
11867 	int i;
11868 	r_decalsystem_splatqueue_t *queue;
11869 
11870 	for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11871 		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);
11872 	r_decalsystem_numqueued = 0;
11873 }
11874 
11875 extern cvar_t cl_decals_max;
R_DrawModelDecals_FadeEntity(entity_render_t * ent)11876 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11877 {
11878 	int i;
11879 	decalsystem_t *decalsystem = &ent->decalsystem;
11880 	int numdecals;
11881 	unsigned int killsequence;
11882 	tridecal_t *decal;
11883 	float frametime;
11884 	float lifetime;
11885 
11886 	if (!decalsystem->numdecals)
11887 		return;
11888 
11889 	if (r_showsurfaces.integer)
11890 		return;
11891 
11892 	if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11893 	{
11894 		R_DecalSystem_Reset(decalsystem);
11895 		return;
11896 	}
11897 
11898 	killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11899 	lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11900 
11901 	if (decalsystem->lastupdatetime)
11902 		frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11903 	else
11904 		frametime = 0;
11905 	decalsystem->lastupdatetime = r_refdef.scene.time;
11906 	numdecals = decalsystem->numdecals;
11907 
11908 	for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11909 	{
11910 		if (decal->color4f[0][3])
11911 		{
11912 			decal->lived += frametime;
11913 			if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11914 			{
11915 				memset(decal, 0, sizeof(*decal));
11916 				if (decalsystem->freedecal > i)
11917 					decalsystem->freedecal = i;
11918 			}
11919 		}
11920 	}
11921 	decal = decalsystem->decals;
11922 	while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11923 		numdecals--;
11924 
11925 	// collapse the array by shuffling the tail decals into the gaps
11926 	for (;;)
11927 	{
11928 		while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11929 			decalsystem->freedecal++;
11930 		if (decalsystem->freedecal == numdecals)
11931 			break;
11932 		decal[decalsystem->freedecal] = decal[--numdecals];
11933 	}
11934 
11935 	decalsystem->numdecals = numdecals;
11936 
11937 	if (numdecals <= 0)
11938 	{
11939 		// if there are no decals left, reset decalsystem
11940 		R_DecalSystem_Reset(decalsystem);
11941 	}
11942 }
11943 
11944 extern skinframe_t *decalskinframe;
R_DrawModelDecals_Entity(entity_render_t * ent)11945 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11946 {
11947 	int i;
11948 	decalsystem_t *decalsystem = &ent->decalsystem;
11949 	int numdecals;
11950 	tridecal_t *decal;
11951 	float faderate;
11952 	float alpha;
11953 	float *v3f;
11954 	float *c4f;
11955 	float *t2f;
11956 	const int *e;
11957 	const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11958 	int numtris = 0;
11959 
11960 	numdecals = decalsystem->numdecals;
11961 	if (!numdecals)
11962 		return;
11963 
11964 	if (r_showsurfaces.integer)
11965 		return;
11966 
11967 	if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11968 	{
11969 		R_DecalSystem_Reset(decalsystem);
11970 		return;
11971 	}
11972 
11973 	// if the model is static it doesn't matter what value we give for
11974 	// wantnormals and wanttangents, so this logic uses only rules applicable
11975 	// to a model, knowing that they are meaningless otherwise
11976 	RSurf_ActiveModelEntity(ent, false, false, false);
11977 
11978 	decalsystem->lastupdatetime = r_refdef.scene.time;
11979 
11980 	faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11981 
11982 	// update vertex positions for animated models
11983 	v3f = decalsystem->vertex3f;
11984 	c4f = decalsystem->color4f;
11985 	t2f = decalsystem->texcoord2f;
11986 	for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11987 	{
11988 		if (!decal->color4f[0][3])
11989 			continue;
11990 
11991 		if (surfacevisible && !surfacevisible[decal->surfaceindex])
11992 			continue;
11993 
11994 		// skip backfaces
11995 		if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11996 			continue;
11997 
11998 		// update color values for fading decals
11999 		if (decal->lived >= cl_decals_time.value)
12000 			alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12001 		else
12002 			alpha = 1.0f;
12003 
12004 		c4f[ 0] = decal->color4f[0][0] * alpha;
12005 		c4f[ 1] = decal->color4f[0][1] * alpha;
12006 		c4f[ 2] = decal->color4f[0][2] * alpha;
12007 		c4f[ 3] = 1;
12008 		c4f[ 4] = decal->color4f[1][0] * alpha;
12009 		c4f[ 5] = decal->color4f[1][1] * alpha;
12010 		c4f[ 6] = decal->color4f[1][2] * alpha;
12011 		c4f[ 7] = 1;
12012 		c4f[ 8] = decal->color4f[2][0] * alpha;
12013 		c4f[ 9] = decal->color4f[2][1] * alpha;
12014 		c4f[10] = decal->color4f[2][2] * alpha;
12015 		c4f[11] = 1;
12016 
12017 		t2f[0] = decal->texcoord2f[0][0];
12018 		t2f[1] = decal->texcoord2f[0][1];
12019 		t2f[2] = decal->texcoord2f[1][0];
12020 		t2f[3] = decal->texcoord2f[1][1];
12021 		t2f[4] = decal->texcoord2f[2][0];
12022 		t2f[5] = decal->texcoord2f[2][1];
12023 
12024 		// update vertex positions for animated models
12025 		if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12026 		{
12027 			e = rsurface.modelelement3i + 3*decal->triangleindex;
12028 			VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12029 			VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12030 			VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12031 		}
12032 		else
12033 		{
12034 			VectorCopy(decal->vertex3f[0], v3f);
12035 			VectorCopy(decal->vertex3f[1], v3f + 3);
12036 			VectorCopy(decal->vertex3f[2], v3f + 6);
12037 		}
12038 
12039 		if (r_refdef.fogenabled)
12040 		{
12041 			alpha = RSurf_FogVertex(v3f);
12042 			VectorScale(c4f, alpha, c4f);
12043 			alpha = RSurf_FogVertex(v3f + 3);
12044 			VectorScale(c4f + 4, alpha, c4f + 4);
12045 			alpha = RSurf_FogVertex(v3f + 6);
12046 			VectorScale(c4f + 8, alpha, c4f + 8);
12047 		}
12048 
12049 		v3f += 9;
12050 		c4f += 12;
12051 		t2f += 6;
12052 		numtris++;
12053 	}
12054 
12055 	if (numtris > 0)
12056 	{
12057 		r_refdef.stats[r_stat_drawndecals] += numtris;
12058 
12059 		// now render the decals all at once
12060 		// (this assumes they all use one particle font texture!)
12061 		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);
12062 //		R_Mesh_ResetTextureState();
12063 		R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12064 		GL_DepthMask(false);
12065 		GL_DepthRange(0, 1);
12066 		GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12067 		GL_DepthTest(true);
12068 		GL_CullFace(GL_NONE);
12069 		GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12070 		R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12071 		R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12072 	}
12073 }
12074 
R_DrawModelDecals(void)12075 static void R_DrawModelDecals(void)
12076 {
12077 	int i, numdecals;
12078 
12079 	// fade faster when there are too many decals
12080 	numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12081 	for (i = 0;i < r_refdef.scene.numentities;i++)
12082 		numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12083 
12084 	R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12085 	for (i = 0;i < r_refdef.scene.numentities;i++)
12086 		if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12087 			R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12088 
12089 	R_DecalSystem_ApplySplatEntitiesQueue();
12090 
12091 	numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12092 	for (i = 0;i < r_refdef.scene.numentities;i++)
12093 		numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12094 
12095 	r_refdef.stats[r_stat_totaldecals] += numdecals;
12096 
12097 	if (r_showsurfaces.integer)
12098 		return;
12099 
12100 	R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12101 
12102 	for (i = 0;i < r_refdef.scene.numentities;i++)
12103 	{
12104 		if (!r_refdef.viewcache.entityvisible[i])
12105 			continue;
12106 		if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12107 			R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12108 	}
12109 }
12110 
12111 extern cvar_t mod_collision_bih;
R_DrawDebugModel(void)12112 static void R_DrawDebugModel(void)
12113 {
12114 	entity_render_t *ent = rsurface.entity;
12115 	int i, j, flagsmask;
12116 	const msurface_t *surface;
12117 	dp_model_t *model = ent->model;
12118 
12119 	if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12120 		return;
12121 
12122 	if (r_showoverdraw.value > 0)
12123 	{
12124 		float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12125 		flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12126 		R_SetupShader_Generic_NoTexture(false, false);
12127 		GL_DepthTest(false);
12128 		GL_DepthMask(false);
12129 		GL_DepthRange(0, 1);
12130 		GL_BlendFunc(GL_ONE, GL_ONE);
12131 		for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12132 		{
12133 			if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12134 				continue;
12135 			rsurface.texture = R_GetCurrentTexture(surface->texture);
12136 			if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12137 			{
12138 				RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12139 				GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12140 				if (!rsurface.texture->currentlayers->depthmask)
12141 					GL_Color(c, 0, 0, 1.0f);
12142 				else if (ent == r_refdef.scene.worldentity)
12143 					GL_Color(c, c, c, 1.0f);
12144 				else
12145 					GL_Color(0, c, 0, 1.0f);
12146 				R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12147 				RSurf_DrawBatch();
12148 			}
12149 		}
12150 		rsurface.texture = NULL;
12151 	}
12152 
12153 	flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12154 
12155 //	R_Mesh_ResetTextureState();
12156 	R_SetupShader_Generic_NoTexture(false, false);
12157 	GL_DepthRange(0, 1);
12158 	GL_DepthTest(!r_showdisabledepthtest.integer);
12159 	GL_DepthMask(false);
12160 	GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12161 
12162 	if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12163 	{
12164 		int triangleindex;
12165 		int bihleafindex;
12166 		qboolean cullbox = false;
12167 		const q3mbrush_t *brush;
12168 		const bih_t *bih = &model->collision_bih;
12169 		const bih_leaf_t *bihleaf;
12170 		float vertex3f[3][3];
12171 		GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12172 		for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12173 		{
12174 			if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12175 				continue;
12176 			switch (bihleaf->type)
12177 			{
12178 			case BIH_BRUSH:
12179 				brush = model->brush.data_brushes + bihleaf->itemindex;
12180 				if (brush->colbrushf && brush->colbrushf->numtriangles)
12181 				{
12182 					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);
12183 					R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12184 					R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12185 				}
12186 				break;
12187 			case BIH_COLLISIONTRIANGLE:
12188 				triangleindex = bihleaf->itemindex;
12189 				VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12190 				VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12191 				VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12192 				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);
12193 				R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12194 				R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12195 				break;
12196 			case BIH_RENDERTRIANGLE:
12197 				triangleindex = bihleaf->itemindex;
12198 				VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12199 				VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12200 				VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12201 				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);
12202 				R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12203 				R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12204 				break;
12205 			}
12206 		}
12207 	}
12208 
12209 	GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12210 
12211 #ifndef USE_GLES2
12212 	if (r_showtris.integer && qglPolygonMode)
12213 	{
12214 		if (r_showdisabledepthtest.integer)
12215 		{
12216 			GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12217 			GL_DepthMask(false);
12218 		}
12219 		else
12220 		{
12221 			GL_BlendFunc(GL_ONE, GL_ZERO);
12222 			GL_DepthMask(true);
12223 		}
12224 		qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12225 		for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12226 		{
12227 			if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12228 				continue;
12229 			rsurface.texture = R_GetCurrentTexture(surface->texture);
12230 			if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12231 			{
12232 				RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12233 				if (!rsurface.texture->currentlayers->depthmask)
12234 					GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12235 				else if (ent == r_refdef.scene.worldentity)
12236 					GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12237 				else
12238 					GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12239 				R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12240 				RSurf_DrawBatch();
12241 			}
12242 		}
12243 		qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12244 		rsurface.texture = NULL;
12245 	}
12246 
12247 	if (r_shownormals.value != 0 && qglBegin)
12248 	{
12249 		int l, k;
12250 		vec3_t v;
12251 		if (r_showdisabledepthtest.integer)
12252 		{
12253 			GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12254 			GL_DepthMask(false);
12255 		}
12256 		else
12257 		{
12258 			GL_BlendFunc(GL_ONE, GL_ZERO);
12259 			GL_DepthMask(true);
12260 		}
12261 		for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12262 		{
12263 			if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12264 				continue;
12265 			rsurface.texture = R_GetCurrentTexture(surface->texture);
12266 			if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12267 			{
12268 				RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12269 				qglBegin(GL_LINES);
12270 				if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12271 				{
12272 					for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12273 					{
12274 						VectorCopy(rsurface.batchvertex3f + l * 3, v);
12275 						GL_Color(0, 0, r_refdef.view.colorscale, 1);
12276 						qglVertex3f(v[0], v[1], v[2]);
12277 						VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12278 						GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12279 						qglVertex3f(v[0], v[1], v[2]);
12280 					}
12281 				}
12282 				if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12283 				{
12284 					for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12285 					{
12286 						VectorCopy(rsurface.batchvertex3f + l * 3, v);
12287 						GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12288 						qglVertex3f(v[0], v[1], v[2]);
12289 						VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12290 						GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12291 						qglVertex3f(v[0], v[1], v[2]);
12292 					}
12293 				}
12294 				if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12295 				{
12296 					for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12297 					{
12298 						VectorCopy(rsurface.batchvertex3f + l * 3, v);
12299 						GL_Color(0, r_refdef.view.colorscale, 0, 1);
12300 						qglVertex3f(v[0], v[1], v[2]);
12301 						VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12302 						GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12303 						qglVertex3f(v[0], v[1], v[2]);
12304 					}
12305 				}
12306 				if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12307 				{
12308 					for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12309 					{
12310 						VectorCopy(rsurface.batchvertex3f + l * 3, v);
12311 						GL_Color(0, 0, r_refdef.view.colorscale, 1);
12312 						qglVertex3f(v[0], v[1], v[2]);
12313 						VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12314 						GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12315 						qglVertex3f(v[0], v[1], v[2]);
12316 					}
12317 				}
12318 				qglEnd();
12319 				CHECKGLERROR
12320 			}
12321 		}
12322 		rsurface.texture = NULL;
12323 	}
12324 #endif
12325 }
12326 
12327 int r_maxsurfacelist = 0;
12328 const msurface_t **r_surfacelist = NULL;
R_DrawModelSurfaces(entity_render_t * ent,qboolean skysurfaces,qboolean writedepth,qboolean depthonly,qboolean debug,qboolean prepass)12329 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12330 {
12331 	int i, j, endj, flagsmask;
12332 	dp_model_t *model = ent->model;
12333 	msurface_t *surfaces;
12334 	unsigned char *update;
12335 	int numsurfacelist = 0;
12336 	if (model == NULL)
12337 		return;
12338 
12339 	if (r_maxsurfacelist < model->num_surfaces)
12340 	{
12341 		r_maxsurfacelist = model->num_surfaces;
12342 		if (r_surfacelist)
12343 			Mem_Free((msurface_t **)r_surfacelist);
12344 		r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12345 	}
12346 
12347 	if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12348 		RSurf_ActiveModelEntity(ent, false, false, false);
12349 	else if (prepass)
12350 		RSurf_ActiveModelEntity(ent, true, true, true);
12351 	else if (depthonly)
12352 	{
12353 		switch (vid.renderpath)
12354 		{
12355 		case RENDERPATH_GL20:
12356 		case RENDERPATH_D3D9:
12357 		case RENDERPATH_D3D10:
12358 		case RENDERPATH_D3D11:
12359 		case RENDERPATH_SOFT:
12360 		case RENDERPATH_GLES2:
12361 			RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12362 			break;
12363 		case RENDERPATH_GL11:
12364 		case RENDERPATH_GL13:
12365 		case RENDERPATH_GLES1:
12366 			RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12367 			break;
12368 		}
12369 	}
12370 	else
12371 	{
12372 		switch (vid.renderpath)
12373 		{
12374 		case RENDERPATH_GL20:
12375 		case RENDERPATH_D3D9:
12376 		case RENDERPATH_D3D10:
12377 		case RENDERPATH_D3D11:
12378 		case RENDERPATH_SOFT:
12379 		case RENDERPATH_GLES2:
12380 			RSurf_ActiveModelEntity(ent, true, true, false);
12381 			break;
12382 		case RENDERPATH_GL11:
12383 		case RENDERPATH_GL13:
12384 		case RENDERPATH_GLES1:
12385 			RSurf_ActiveModelEntity(ent, true, false, false);
12386 			break;
12387 		}
12388 	}
12389 
12390 	surfaces = model->data_surfaces;
12391 	update = model->brushq1.lightmapupdateflags;
12392 
12393 	// update light styles
12394 	if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12395 	{
12396 		model_brush_lightstyleinfo_t *style;
12397 		for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12398 		{
12399 			if (style->value != r_refdef.scene.lightstylevalue[style->style])
12400 			{
12401 				int *list = style->surfacelist;
12402 				style->value = r_refdef.scene.lightstylevalue[style->style];
12403 				for (j = 0;j < style->numsurfaces;j++)
12404 					update[list[j]] = true;
12405 			}
12406 		}
12407 	}
12408 
12409 	flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12410 
12411 	if (debug)
12412 	{
12413 		R_DrawDebugModel();
12414 		rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12415 		return;
12416 	}
12417 
12418 	rsurface.lightmaptexture = NULL;
12419 	rsurface.deluxemaptexture = NULL;
12420 	rsurface.uselightmaptexture = false;
12421 	rsurface.texture = NULL;
12422 	rsurface.rtlight = NULL;
12423 	numsurfacelist = 0;
12424 	// add visible surfaces to draw list
12425 	if (ent == r_refdef.scene.worldentity)
12426 	{
12427 		// for the world entity, check surfacevisible
12428 		for (i = 0;i < model->nummodelsurfaces;i++)
12429 		{
12430 			j = model->sortedmodelsurfaces[i];
12431 			if (r_refdef.viewcache.world_surfacevisible[j])
12432 				r_surfacelist[numsurfacelist++] = surfaces + j;
12433 		}
12434 	}
12435 	else
12436 	{
12437 		// add all surfaces
12438 		for (i = 0; i < model->nummodelsurfaces; i++)
12439 			r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12440 	}
12441 	// don't do anything if there were no surfaces
12442 	if (!numsurfacelist)
12443 	{
12444 		rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12445 		return;
12446 	}
12447 	// update lightmaps if needed
12448 	if (update)
12449 	{
12450 		int updated = 0;
12451 		for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12452 		{
12453 			if (update[j])
12454 			{
12455 				updated++;
12456 				R_BuildLightMap(ent, surfaces + j);
12457 			}
12458 		}
12459 	}
12460 
12461 	R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12462 
12463 	// add to stats if desired
12464 	if (r_speeds.integer && !skysurfaces && !depthonly)
12465 	{
12466 		r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12467 		for (j = 0;j < numsurfacelist;j++)
12468 			r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12469 	}
12470 
12471 	rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12472 }
12473 
R_DrawCustomSurface(skinframe_t * skinframe,const matrix4x4_t * texmatrix,int materialflags,int firstvertex,int numvertices,int firsttriangle,int numtriangles,qboolean writedepth,qboolean prepass)12474 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12475 {
12476 	int q;
12477 	static texture_t texture;
12478 	static msurface_t surface;
12479 	const msurface_t *surfacelist = &surface;
12480 
12481 	// fake enough texture and surface state to render this geometry
12482 
12483 	texture.update_lastrenderframe = -1; // regenerate this texture
12484 	texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12485 	texture.basealpha = 1.0f;
12486 	texture.currentskinframe = skinframe;
12487 	texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12488 	texture.offsetmapping = OFFSETMAPPING_OFF;
12489 	texture.offsetscale = 1;
12490 	texture.specularscalemod = 1;
12491 	texture.specularpowermod = 1;
12492 	texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12493 	// WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12494 	// JUST GREP FOR "specularscalemod = 1".
12495 
12496 	for (q = 0; q < 3; q++)
12497 	{
12498 		texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12499 		texture.render_modellight_lightdir[q] = q == 2;
12500 		texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12501 		texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12502 		texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12503 		texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12504 		texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12505 		texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12506 		texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12507 		texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12508 	}
12509 	texture.currentalpha = 1.0f;
12510 
12511 	surface.texture = &texture;
12512 	surface.num_triangles = numtriangles;
12513 	surface.num_firsttriangle = firsttriangle;
12514 	surface.num_vertices = numvertices;
12515 	surface.num_firstvertex = firstvertex;
12516 
12517 	// now render it
12518 	rsurface.texture = R_GetCurrentTexture(surface.texture);
12519 	rsurface.lightmaptexture = NULL;
12520 	rsurface.deluxemaptexture = NULL;
12521 	rsurface.uselightmaptexture = false;
12522 	R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12523 }
12524 
R_DrawCustomSurface_Texture(texture_t * texture,const matrix4x4_t * texmatrix,int materialflags,int firstvertex,int numvertices,int firsttriangle,int numtriangles,qboolean writedepth,qboolean prepass)12525 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)
12526 {
12527 	static msurface_t surface;
12528 	const msurface_t *surfacelist = &surface;
12529 
12530 	// fake enough texture and surface state to render this geometry
12531 	surface.texture = texture;
12532 	surface.num_triangles = numtriangles;
12533 	surface.num_firsttriangle = firsttriangle;
12534 	surface.num_vertices = numvertices;
12535 	surface.num_firstvertex = firstvertex;
12536 
12537 	// now render it
12538 	rsurface.texture = R_GetCurrentTexture(surface.texture);
12539 	rsurface.lightmaptexture = NULL;
12540 	rsurface.deluxemaptexture = NULL;
12541 	rsurface.uselightmaptexture = false;
12542 	R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12543 }
12544