]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
UNMERGE! Refactored R_UpdateEntityLighting to CL_UpdateEntityShading, which sets...
[xonotic/darkplaces.git] / gl_rmain.c
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 "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 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!"};
67 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!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 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)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 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)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84
85 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"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 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%)" };
98 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)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 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"};
102 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"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 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"};
105 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"};
106 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"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 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)"};
116 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)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 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"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 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"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 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"};
132 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"};
133
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 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."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 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."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 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."};
145 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."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 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"};
148 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"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 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"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 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
159 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
160
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169
170 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)"};
171 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"};
172
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176
177 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"};
178 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"};
179 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"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 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"};
183 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)"};
184 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)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 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)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 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)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 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)"};
193 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)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 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"};
196 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."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206
207 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)"};
208 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)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 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"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 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"};
215 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"};
216 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)"};
217
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243
244 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"};
245
246 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"};
247
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251
252 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)"};
253 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)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 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"};
259
260 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."};
261
262 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)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {
265         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
269 };
270
271 extern cvar_t v_glslgamma_2d;
272
273 extern qboolean v_flipped_state;
274
275 r_framebufferstate_t r_fb;
276
277 /// shadow volume bsp struct with automatically growing nodes buffer
278 svbsp_t r_svbsp;
279
280 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
281
282 rtexture_t *r_texture_blanknormalmap;
283 rtexture_t *r_texture_white;
284 rtexture_t *r_texture_grey128;
285 rtexture_t *r_texture_black;
286 rtexture_t *r_texture_notexture;
287 rtexture_t *r_texture_whitecube;
288 rtexture_t *r_texture_normalizationcube;
289 rtexture_t *r_texture_fogattenuation;
290 rtexture_t *r_texture_fogheighttexture;
291 rtexture_t *r_texture_gammaramps;
292 unsigned int r_texture_gammaramps_serial;
293 //rtexture_t *r_texture_fogintensity;
294 rtexture_t *r_texture_reflectcube;
295
296 // TODO: hash lookups?
297 typedef struct cubemapinfo_s
298 {
299         char basename[64];
300         rtexture_t *texture;
301 }
302 cubemapinfo_t;
303
304 int r_texture_numcubemaps;
305 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
306
307 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
308 unsigned int r_numqueries;
309 unsigned int r_maxqueries;
310
311 typedef struct r_qwskincache_s
312 {
313         char name[MAX_QPATH];
314         skinframe_t *skinframe;
315 }
316 r_qwskincache_t;
317
318 static r_qwskincache_t *r_qwskincache;
319 static int r_qwskincache_size;
320
321 /// vertex coordinates for a quad that covers the screen exactly
322 extern const float r_screenvertex3f[12];
323 extern const float r_d3dscreenvertex3f[12];
324 const float r_screenvertex3f[12] =
325 {
326         0, 0, 0,
327         1, 0, 0,
328         1, 1, 0,
329         0, 1, 0
330 };
331 const float r_d3dscreenvertex3f[12] =
332 {
333         0, 1, 0,
334         1, 1, 0,
335         1, 0, 0,
336         0, 0, 0
337 };
338
339 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
340 {
341         int i;
342         for (i = 0;i < verts;i++)
343         {
344                 out[0] = in[0] * r;
345                 out[1] = in[1] * g;
346                 out[2] = in[2] * b;
347                 out[3] = in[3];
348                 in += 4;
349                 out += 4;
350         }
351 }
352
353 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
354 {
355         int i;
356         for (i = 0;i < verts;i++)
357         {
358                 out[0] = r;
359                 out[1] = g;
360                 out[2] = b;
361                 out[3] = a;
362                 out += 4;
363         }
364 }
365
366 // FIXME: move this to client?
367 void FOG_clear(void)
368 {
369         if (gamemode == GAME_NEHAHRA)
370         {
371                 Cvar_Set("gl_fogenable", "0");
372                 Cvar_Set("gl_fogdensity", "0.2");
373                 Cvar_Set("gl_fogred", "0.3");
374                 Cvar_Set("gl_foggreen", "0.3");
375                 Cvar_Set("gl_fogblue", "0.3");
376         }
377         r_refdef.fog_density = 0;
378         r_refdef.fog_red = 0;
379         r_refdef.fog_green = 0;
380         r_refdef.fog_blue = 0;
381         r_refdef.fog_alpha = 1;
382         r_refdef.fog_start = 0;
383         r_refdef.fog_end = 16384;
384         r_refdef.fog_height = 1<<30;
385         r_refdef.fog_fadedepth = 128;
386         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
387 }
388
389 static void R_BuildBlankTextures(void)
390 {
391         unsigned char data[4];
392         data[2] = 128; // normal X
393         data[1] = 128; // normal Y
394         data[0] = 255; // normal Z
395         data[3] = 255; // height
396         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 255;
398         data[1] = 255;
399         data[2] = 255;
400         data[3] = 255;
401         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 128;
403         data[1] = 128;
404         data[2] = 128;
405         data[3] = 255;
406         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407         data[0] = 0;
408         data[1] = 0;
409         data[2] = 0;
410         data[3] = 255;
411         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
412 }
413
414 static void R_BuildNoTexture(void)
415 {
416         int x, y;
417         unsigned char pix[16][16][4];
418         // this makes a light grey/dark grey checkerboard texture
419         for (y = 0;y < 16;y++)
420         {
421                 for (x = 0;x < 16;x++)
422                 {
423                         if ((y < 8) ^ (x < 8))
424                         {
425                                 pix[y][x][0] = 128;
426                                 pix[y][x][1] = 128;
427                                 pix[y][x][2] = 128;
428                                 pix[y][x][3] = 255;
429                         }
430                         else
431                         {
432                                 pix[y][x][0] = 64;
433                                 pix[y][x][1] = 64;
434                                 pix[y][x][2] = 64;
435                                 pix[y][x][3] = 255;
436                         }
437                 }
438         }
439         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
440 }
441
442 static void R_BuildWhiteCube(void)
443 {
444         unsigned char data[6*1*1*4];
445         memset(data, 255, sizeof(data));
446         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
447 }
448
449 static void R_BuildNormalizationCube(void)
450 {
451         int x, y, side;
452         vec3_t v;
453         vec_t s, t, intensity;
454 #define NORMSIZE 64
455         unsigned char *data;
456         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
457         for (side = 0;side < 6;side++)
458         {
459                 for (y = 0;y < NORMSIZE;y++)
460                 {
461                         for (x = 0;x < NORMSIZE;x++)
462                         {
463                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 switch(side)
466                                 {
467                                 default:
468                                 case 0:
469                                         v[0] = 1;
470                                         v[1] = -t;
471                                         v[2] = -s;
472                                         break;
473                                 case 1:
474                                         v[0] = -1;
475                                         v[1] = -t;
476                                         v[2] = s;
477                                         break;
478                                 case 2:
479                                         v[0] = s;
480                                         v[1] = 1;
481                                         v[2] = t;
482                                         break;
483                                 case 3:
484                                         v[0] = s;
485                                         v[1] = -1;
486                                         v[2] = -t;
487                                         break;
488                                 case 4:
489                                         v[0] = s;
490                                         v[1] = -t;
491                                         v[2] = 1;
492                                         break;
493                                 case 5:
494                                         v[0] = -s;
495                                         v[1] = -t;
496                                         v[2] = -1;
497                                         break;
498                                 }
499                                 intensity = 127.0f / sqrt(DotProduct(v, v));
500                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
501                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
502                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
503                                 data[((side*64+y)*64+x)*4+3] = 255;
504                         }
505                 }
506         }
507         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508         Mem_Free(data);
509 }
510
511 static void R_BuildFogTexture(void)
512 {
513         int x, b;
514 #define FOGWIDTH 256
515         unsigned char data1[FOGWIDTH][4];
516         //unsigned char data2[FOGWIDTH][4];
517         double d, r, alpha;
518
519         r_refdef.fogmasktable_start = r_refdef.fog_start;
520         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
521         r_refdef.fogmasktable_range = r_refdef.fogrange;
522         r_refdef.fogmasktable_density = r_refdef.fog_density;
523
524         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
525         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
526         {
527                 d = (x * r - r_refdef.fogmasktable_start);
528                 if(developer_extra.integer)
529                         Con_DPrintf("%f ", d);
530                 d = max(0, d);
531                 if (r_fog_exp2.integer)
532                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
533                 else
534                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
535                 if(developer_extra.integer)
536                         Con_DPrintf(" : %f ", alpha);
537                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
538                 if(developer_extra.integer)
539                         Con_DPrintf(" = %f\n", alpha);
540                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
541         }
542
543         for (x = 0;x < FOGWIDTH;x++)
544         {
545                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
546                 data1[x][0] = b;
547                 data1[x][1] = b;
548                 data1[x][2] = b;
549                 data1[x][3] = 255;
550                 //data2[x][0] = 255 - b;
551                 //data2[x][1] = 255 - b;
552                 //data2[x][2] = 255 - b;
553                 //data2[x][3] = 255;
554         }
555         if (r_texture_fogattenuation)
556         {
557                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559         }
560         else
561         {
562                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
563                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
564         }
565 }
566
567 static void R_BuildFogHeightTexture(void)
568 {
569         unsigned char *inpixels;
570         int size;
571         int x;
572         int y;
573         int j;
574         float c[4];
575         float f;
576         inpixels = NULL;
577         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
578         if (r_refdef.fogheighttexturename[0])
579                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
580         if (!inpixels)
581         {
582                 r_refdef.fog_height_tablesize = 0;
583                 if (r_texture_fogheighttexture)
584                         R_FreeTexture(r_texture_fogheighttexture);
585                 r_texture_fogheighttexture = NULL;
586                 if (r_refdef.fog_height_table2d)
587                         Mem_Free(r_refdef.fog_height_table2d);
588                 r_refdef.fog_height_table2d = NULL;
589                 if (r_refdef.fog_height_table1d)
590                         Mem_Free(r_refdef.fog_height_table1d);
591                 r_refdef.fog_height_table1d = NULL;
592                 return;
593         }
594         size = image_width;
595         r_refdef.fog_height_tablesize = size;
596         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
597         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
598         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
599         Mem_Free(inpixels);
600         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
601         // average fog color table accounting for every fog layer between a point
602         // and the camera.  (Note: attenuation is handled separately!)
603         for (y = 0;y < size;y++)
604         {
605                 for (x = 0;x < size;x++)
606                 {
607                         Vector4Clear(c);
608                         f = 0;
609                         if (x < y)
610                         {
611                                 for (j = x;j <= y;j++)
612                                 {
613                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
614                                         f++;
615                                 }
616                         }
617                         else
618                         {
619                                 for (j = x;j >= y;j--)
620                                 {
621                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
622                                         f++;
623                                 }
624                         }
625                         f = 1.0f / f;
626                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
627                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
630                 }
631         }
632         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
633 }
634
635 //=======================================================================================================================================================
636
637 static const char *builtinshaderstrings[] =
638 {
639 #include "shader_glsl.h"
640 0
641 };
642
643 const char *builtinhlslshaderstrings[] =
644 {
645 #include "shader_hlsl.h"
646 0
647 };
648
649 //=======================================================================================================================================================
650
651 typedef struct shaderpermutationinfo_s
652 {
653         const char *pretext;
654         const char *name;
655 }
656 shaderpermutationinfo_t;
657
658 typedef struct shadermodeinfo_s
659 {
660         const char *sourcebasename;
661         const char *extension;
662         const char **builtinshaderstrings;
663         const char *pretext;
664         const char *name;
665         char *filename;
666         char *builtinstring;
667         int builtincrc;
668 }
669 shadermodeinfo_t;
670
671 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
672 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
673 {
674         {"#define USEDIFFUSE\n", " diffuse"},
675         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
676         {"#define USEVIEWTINT\n", " viewtint"},
677         {"#define USECOLORMAPPING\n", " colormapping"},
678         {"#define USESATURATION\n", " saturation"},
679         {"#define USEFOGINSIDE\n", " foginside"},
680         {"#define USEFOGOUTSIDE\n", " fogoutside"},
681         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
682         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
683         {"#define USEGAMMARAMPS\n", " gammaramps"},
684         {"#define USECUBEFILTER\n", " cubefilter"},
685         {"#define USEGLOW\n", " glow"},
686         {"#define USEBLOOM\n", " bloom"},
687         {"#define USESPECULAR\n", " specular"},
688         {"#define USEPOSTPROCESSING\n", " postprocessing"},
689         {"#define USEREFLECTION\n", " reflection"},
690         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
691         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
692         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
693         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
694         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
695         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
696         {"#define USEALPHAKILL\n", " alphakill"},
697         {"#define USEREFLECTCUBE\n", " reflectcube"},
698         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
699         {"#define USEBOUNCEGRID\n", " bouncegrid"},
700         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
701         {"#define USETRIPPY\n", " trippy"},
702         {"#define USEDEPTHRGB\n", " depthrgb"},
703         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
704         {"#define USESKELETAL\n", " skeletal"},
705         {"#define USEOCCLUDE\n", " occlude"}
706 };
707
708 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
709 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
710 {
711         // SHADERLANGUAGE_GLSL
712         {
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730         },
731         // SHADERLANGUAGE_HLSL
732         {
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
750         },
751 };
752
753 struct r_glsl_permutation_s;
754 typedef struct r_glsl_permutation_s
755 {
756         /// hash lookup data
757         struct r_glsl_permutation_s *hashnext;
758         unsigned int mode;
759         dpuint64 permutation;
760
761         /// indicates if we have tried compiling this permutation already
762         qboolean compiled;
763         /// 0 if compilation failed
764         int program;
765         // texture units assigned to each detected uniform
766         int tex_Texture_First;
767         int tex_Texture_Second;
768         int tex_Texture_GammaRamps;
769         int tex_Texture_Normal;
770         int tex_Texture_Color;
771         int tex_Texture_Gloss;
772         int tex_Texture_Glow;
773         int tex_Texture_SecondaryNormal;
774         int tex_Texture_SecondaryColor;
775         int tex_Texture_SecondaryGloss;
776         int tex_Texture_SecondaryGlow;
777         int tex_Texture_Pants;
778         int tex_Texture_Shirt;
779         int tex_Texture_FogHeightTexture;
780         int tex_Texture_FogMask;
781         int tex_Texture_Lightmap;
782         int tex_Texture_Deluxemap;
783         int tex_Texture_Attenuation;
784         int tex_Texture_Cube;
785         int tex_Texture_Refraction;
786         int tex_Texture_Reflection;
787         int tex_Texture_ShadowMap2D;
788         int tex_Texture_CubeProjection;
789         int tex_Texture_ScreenNormalMap;
790         int tex_Texture_ScreenDiffuse;
791         int tex_Texture_ScreenSpecular;
792         int tex_Texture_ReflectMask;
793         int tex_Texture_ReflectCube;
794         int tex_Texture_BounceGrid;
795         /// locations of detected uniforms in program object, or -1 if not found
796         int loc_Texture_First;
797         int loc_Texture_Second;
798         int loc_Texture_GammaRamps;
799         int loc_Texture_Normal;
800         int loc_Texture_Color;
801         int loc_Texture_Gloss;
802         int loc_Texture_Glow;
803         int loc_Texture_SecondaryNormal;
804         int loc_Texture_SecondaryColor;
805         int loc_Texture_SecondaryGloss;
806         int loc_Texture_SecondaryGlow;
807         int loc_Texture_Pants;
808         int loc_Texture_Shirt;
809         int loc_Texture_FogHeightTexture;
810         int loc_Texture_FogMask;
811         int loc_Texture_Lightmap;
812         int loc_Texture_Deluxemap;
813         int loc_Texture_Attenuation;
814         int loc_Texture_Cube;
815         int loc_Texture_Refraction;
816         int loc_Texture_Reflection;
817         int loc_Texture_ShadowMap2D;
818         int loc_Texture_CubeProjection;
819         int loc_Texture_ScreenNormalMap;
820         int loc_Texture_ScreenDiffuse;
821         int loc_Texture_ScreenSpecular;
822         int loc_Texture_ReflectMask;
823         int loc_Texture_ReflectCube;
824         int loc_Texture_BounceGrid;
825         int loc_Alpha;
826         int loc_BloomBlur_Parameters;
827         int loc_ClientTime;
828         int loc_Color_Ambient;
829         int loc_Color_Diffuse;
830         int loc_Color_Specular;
831         int loc_Color_Glow;
832         int loc_Color_Pants;
833         int loc_Color_Shirt;
834         int loc_DeferredColor_Ambient;
835         int loc_DeferredColor_Diffuse;
836         int loc_DeferredColor_Specular;
837         int loc_DeferredMod_Diffuse;
838         int loc_DeferredMod_Specular;
839         int loc_DistortScaleRefractReflect;
840         int loc_EyePosition;
841         int loc_FogColor;
842         int loc_FogHeightFade;
843         int loc_FogPlane;
844         int loc_FogPlaneViewDist;
845         int loc_FogRangeRecip;
846         int loc_LightColor;
847         int loc_LightDir;
848         int loc_LightPosition;
849         int loc_OffsetMapping_ScaleSteps;
850         int loc_OffsetMapping_LodDistance;
851         int loc_OffsetMapping_Bias;
852         int loc_PixelSize;
853         int loc_ReflectColor;
854         int loc_ReflectFactor;
855         int loc_ReflectOffset;
856         int loc_RefractColor;
857         int loc_Saturation;
858         int loc_ScreenCenterRefractReflect;
859         int loc_ScreenScaleRefractReflect;
860         int loc_ScreenToDepth;
861         int loc_ShadowMap_Parameters;
862         int loc_ShadowMap_TextureScale;
863         int loc_SpecularPower;
864         int loc_Skeletal_Transform12;
865         int loc_UserVec1;
866         int loc_UserVec2;
867         int loc_UserVec3;
868         int loc_UserVec4;
869         int loc_ViewTintColor;
870         int loc_ViewToLight;
871         int loc_ModelToLight;
872         int loc_TexMatrix;
873         int loc_BackgroundTexMatrix;
874         int loc_ModelViewProjectionMatrix;
875         int loc_ModelViewMatrix;
876         int loc_PixelToScreenTexCoord;
877         int loc_ModelToReflectCube;
878         int loc_ShadowMapMatrix;
879         int loc_BloomColorSubtract;
880         int loc_NormalmapScrollBlend;
881         int loc_BounceGridMatrix;
882         int loc_BounceGridIntensity;
883         /// uniform block bindings
884         int ubibind_Skeletal_Transform12_UniformBlock;
885         /// uniform block indices
886         int ubiloc_Skeletal_Transform12_UniformBlock;
887 }
888 r_glsl_permutation_t;
889
890 #define SHADERPERMUTATION_HASHSIZE 256
891
892
893 // non-degradable "lightweight" shader parameters to keep the permutations simpler
894 // these can NOT degrade! only use for simple stuff
895 enum
896 {
897         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
898         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
899         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
900         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
903         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
904         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
905         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
906         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
907         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
908         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
909         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
910         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
911 };
912 #define SHADERSTATICPARMS_COUNT 14
913
914 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
915 static int shaderstaticparms_count = 0;
916
917 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
918 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
919
920 extern qboolean r_shadow_shadowmapsampler;
921 extern int r_shadow_shadowmappcf;
922 qboolean R_CompileShader_CheckStaticParms(void)
923 {
924         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
925         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
926         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
927
928         // detect all
929         if (r_glsl_saturation_redcompensate.integer)
930                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
931         if (r_glsl_vertextextureblend_usebothalphas.integer)
932                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
933         if (r_shadow_glossexact.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
935         if (r_glsl_postprocess.integer)
936         {
937                 if (r_glsl_postprocess_uservec1_enable.integer)
938                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
939                 if (r_glsl_postprocess_uservec2_enable.integer)
940                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
941                 if (r_glsl_postprocess_uservec3_enable.integer)
942                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
943                 if (r_glsl_postprocess_uservec4_enable.integer)
944                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
945         }
946         if (r_fxaa.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
948         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
950
951         if (r_shadow_shadowmapsampler)
952                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
953         if (r_shadow_shadowmappcf > 1)
954                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
955         else if (r_shadow_shadowmappcf)
956                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
957         if (r_celshading.integer)
958                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
959         if (r_celoutlines.integer)
960                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
961
962         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
963 }
964
965 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
966         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
967                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
968         else \
969                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
970 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
971 {
972         shaderstaticparms_count = 0;
973
974         // emit all
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
989 }
990
991 /// information about each possible shader permutation
992 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
993 /// currently selected permutation
994 r_glsl_permutation_t *r_glsl_permutation;
995 /// storage for permutations linked in the hash table
996 memexpandablearray_t r_glsl_permutationarray;
997
998 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
999 {
1000         //unsigned int hashdepth = 0;
1001         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1002         r_glsl_permutation_t *p;
1003         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1004         {
1005                 if (p->mode == mode && p->permutation == permutation)
1006                 {
1007                         //if (hashdepth > 10)
1008                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1009                         return p;
1010                 }
1011                 //hashdepth++;
1012         }
1013         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1014         p->mode = mode;
1015         p->permutation = permutation;
1016         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1017         r_glsl_permutationhash[mode][hashindex] = p;
1018         //if (hashdepth > 10)
1019         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1020         return p;
1021 }
1022
1023 static char *R_ShaderStrCat(const char **strings)
1024 {
1025         char *string, *s;
1026         const char **p = strings;
1027         const char *t;
1028         size_t len = 0;
1029         for (p = strings;(t = *p);p++)
1030                 len += strlen(t);
1031         len++;
1032         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1033         len = 0;
1034         for (p = strings;(t = *p);p++)
1035         {
1036                 len = strlen(t);
1037                 memcpy(s, t, len);
1038                 s += len;
1039         }
1040         *s = 0;
1041         return string;
1042 }
1043
1044 static char *R_ShaderStrCat(const char **strings);
1045 static void R_InitShaderModeInfo(void)
1046 {
1047         int i, language;
1048         shadermodeinfo_t *modeinfo;
1049         // 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)
1050         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1051         {
1052                 for (i = 0; i < SHADERMODE_COUNT; i++)
1053                 {
1054                         char filename[MAX_QPATH];
1055                         modeinfo = &shadermodeinfo[language][i];
1056                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1057                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1058                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1059                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1060                 }
1061         }
1062 }
1063
1064 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1065 {
1066         char *shaderstring;
1067         // if the mode has no filename we have to return the builtin string
1068         if (builtinonly || !modeinfo->filename)
1069                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1070         // note that FS_LoadFile appends a 0 byte to make it a valid string
1071         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1072         if (shaderstring)
1073         {
1074                 if (printfromdisknotice)
1075                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1076                 return shaderstring;
1077         }
1078         // fall back to builtinstring
1079         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127         // if we can do #version 120, we should (this adds the invariant keyword)
1128         else if(vid.support.glshaderversion >= 120)
1129         {
1130                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1131                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1132                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1133                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1134                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1135                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1136         }
1137         // GLES also adds several things from GLSL120
1138         switch(vid.renderpath)
1139         {
1140         case RENDERPATH_GLES2:
1141                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1142                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1143                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1144                 break;
1145         default:
1146                 break;
1147         }
1148
1149         // the first pretext is which type of shader to compile as
1150         // (later these will all be bound together as a program object)
1151         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1152         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1153         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1154
1155         // the second pretext is the mode (for example a light source)
1156         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1157         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1158         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1159         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1160
1161         // now add all the permutation pretexts
1162         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1163         {
1164                 if (permutation & (1ll<<i))
1165                 {
1166                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1167                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1170                 }
1171                 else
1172                 {
1173                         // keep line numbers correct
1174                         vertstrings_list[vertstrings_count++] = "\n";
1175                         geomstrings_list[geomstrings_count++] = "\n";
1176                         fragstrings_list[fragstrings_count++] = "\n";
1177                 }
1178         }
1179
1180         // add static parms
1181         R_CompileShader_AddStaticParms(mode, permutation);
1182         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1183         vertstrings_count += shaderstaticparms_count;
1184         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1185         geomstrings_count += shaderstaticparms_count;
1186         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1187         fragstrings_count += shaderstaticparms_count;
1188
1189         // now append the shader text itself
1190         vertstrings_list[vertstrings_count++] = sourcestring;
1191         geomstrings_list[geomstrings_count++] = sourcestring;
1192         fragstrings_list[fragstrings_count++] = sourcestring;
1193
1194         // compile the shader program
1195         if (vertstrings_count + geomstrings_count + fragstrings_count)
1196                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1197         if (p->program)
1198         {
1199                 CHECKGLERROR
1200                 qglUseProgram(p->program);CHECKGLERROR
1201                 // look up all the uniform variable names we care about, so we don't
1202                 // have to look them up every time we set them
1203
1204 #if 0
1205                 // debugging aid
1206                 {
1207                         GLint activeuniformindex = 0;
1208                         GLint numactiveuniforms = 0;
1209                         char uniformname[128];
1210                         GLsizei uniformnamelength = 0;
1211                         GLint uniformsize = 0;
1212                         GLenum uniformtype = 0;
1213                         memset(uniformname, 0, sizeof(uniformname));
1214                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1215                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1216                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1217                         {
1218                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1219                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1220                         }
1221                 }
1222 #endif
1223
1224                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1225                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1226                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1227                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1228                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1229                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1230                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1231                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1232                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1233                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1234                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1235                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1236                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1237                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1238                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1239                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1240                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1241                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1242                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1243                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1244                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1245                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1246                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1247                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1248                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1249                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1250                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1251                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1252                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1253                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1254                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1255                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1256                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1257                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1258                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1259                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1260                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1261                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1262                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1263                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1264                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1265                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1266                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1267                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1268                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1269                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1270                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1271                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1272                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1273                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1274                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1275                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1276                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1277                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1278                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1279                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1280                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1281                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1282                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1283                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1284                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1285                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1286                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1287                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1288                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1289                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1290                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1291                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1292                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1293                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1294                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1295                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1296                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1297                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1298                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1299                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1300                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1301                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1302                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1303                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1304                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1305                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1306                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1307                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1308                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1309                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1310                 // initialize the samplers to refer to the texture units we use
1311                 p->tex_Texture_First = -1;
1312                 p->tex_Texture_Second = -1;
1313                 p->tex_Texture_GammaRamps = -1;
1314                 p->tex_Texture_Normal = -1;
1315                 p->tex_Texture_Color = -1;
1316                 p->tex_Texture_Gloss = -1;
1317                 p->tex_Texture_Glow = -1;
1318                 p->tex_Texture_SecondaryNormal = -1;
1319                 p->tex_Texture_SecondaryColor = -1;
1320                 p->tex_Texture_SecondaryGloss = -1;
1321                 p->tex_Texture_SecondaryGlow = -1;
1322                 p->tex_Texture_Pants = -1;
1323                 p->tex_Texture_Shirt = -1;
1324                 p->tex_Texture_FogHeightTexture = -1;
1325                 p->tex_Texture_FogMask = -1;
1326                 p->tex_Texture_Lightmap = -1;
1327                 p->tex_Texture_Deluxemap = -1;
1328                 p->tex_Texture_Attenuation = -1;
1329                 p->tex_Texture_Cube = -1;
1330                 p->tex_Texture_Refraction = -1;
1331                 p->tex_Texture_Reflection = -1;
1332                 p->tex_Texture_ShadowMap2D = -1;
1333                 p->tex_Texture_CubeProjection = -1;
1334                 p->tex_Texture_ScreenNormalMap = -1;
1335                 p->tex_Texture_ScreenDiffuse = -1;
1336                 p->tex_Texture_ScreenSpecular = -1;
1337                 p->tex_Texture_ReflectMask = -1;
1338                 p->tex_Texture_ReflectCube = -1;
1339                 p->tex_Texture_BounceGrid = -1;
1340                 // bind the texture samplers in use
1341                 sampler = 0;
1342                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1343                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1344                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1345                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1346                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1347                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1348                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1349                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1353                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1354                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1355                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1356                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1357                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1358                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1359                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1360                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1361                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1362                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1363                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1364                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1365                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1368                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1370                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1371                 // get the uniform block indices so we can bind them
1372 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1373                 if (vid.support.arb_uniform_buffer_object)
1374                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1375                 else
1376 #endif
1377                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1378                 // clear the uniform block bindings
1379                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1380                 // bind the uniform blocks in use
1381                 ubibind = 0;
1382 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1383                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1384 #endif
1385                 // we're done compiling and setting up the shader, at least until it is used
1386                 CHECKGLERROR
1387                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1388         }
1389         else
1390                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1391
1392         // free the strings
1393         if (sourcestring)
1394                 Mem_Free(sourcestring);
1395 }
1396
1397 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1398 {
1399         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1400         if (r_glsl_permutation != perm)
1401         {
1402                 r_glsl_permutation = perm;
1403                 if (!r_glsl_permutation->program)
1404                 {
1405                         if (!r_glsl_permutation->compiled)
1406                         {
1407                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1408                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1409                         }
1410                         if (!r_glsl_permutation->program)
1411                         {
1412                                 // remove features until we find a valid permutation
1413                                 int i;
1414                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1415                                 {
1416                                         // reduce i more quickly whenever it would not remove any bits
1417                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1418                                         if (!(permutation & j))
1419                                                 continue;
1420                                         permutation -= j;
1421                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422                                         if (!r_glsl_permutation->compiled)
1423                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1424                                         if (r_glsl_permutation->program)
1425                                                 break;
1426                                 }
1427                                 if (i >= SHADERPERMUTATION_COUNT)
1428                                 {
1429                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1430                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1431                                         qglUseProgram(0);CHECKGLERROR
1432                                         return; // no bit left to clear, entire mode is broken
1433                                 }
1434                         }
1435                 }
1436                 CHECKGLERROR
1437                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1438         }
1439         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1440         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1441         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1442         CHECKGLERROR
1443 }
1444
1445 #ifdef SUPPORTD3D
1446
1447 #ifdef SUPPORTD3D
1448 #include <d3d9.h>
1449 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1450 extern D3DCAPS9 vid_d3d9caps;
1451 #endif
1452
1453 struct r_hlsl_permutation_s;
1454 typedef struct r_hlsl_permutation_s
1455 {
1456         /// hash lookup data
1457         struct r_hlsl_permutation_s *hashnext;
1458         unsigned int mode;
1459         dpuint64 permutation;
1460
1461         /// indicates if we have tried compiling this permutation already
1462         qboolean compiled;
1463         /// NULL if compilation failed
1464         IDirect3DVertexShader9 *vertexshader;
1465         IDirect3DPixelShader9 *pixelshader;
1466 }
1467 r_hlsl_permutation_t;
1468
1469 typedef enum D3DVSREGISTER_e
1470 {
1471         D3DVSREGISTER_TexMatrix = 0, // float4x4
1472         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1473         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1474         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1475         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1476         D3DVSREGISTER_ModelToLight = 20, // float4x4
1477         D3DVSREGISTER_EyePosition = 24,
1478         D3DVSREGISTER_FogPlane = 25,
1479         D3DVSREGISTER_LightDir = 26,
1480         D3DVSREGISTER_LightPosition = 27,
1481 }
1482 D3DVSREGISTER_t;
1483
1484 typedef enum D3DPSREGISTER_e
1485 {
1486         D3DPSREGISTER_Alpha = 0,
1487         D3DPSREGISTER_BloomBlur_Parameters = 1,
1488         D3DPSREGISTER_ClientTime = 2,
1489         D3DPSREGISTER_Color_Ambient = 3,
1490         D3DPSREGISTER_Color_Diffuse = 4,
1491         D3DPSREGISTER_Color_Specular = 5,
1492         D3DPSREGISTER_Color_Glow = 6,
1493         D3DPSREGISTER_Color_Pants = 7,
1494         D3DPSREGISTER_Color_Shirt = 8,
1495         D3DPSREGISTER_DeferredColor_Ambient = 9,
1496         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1497         D3DPSREGISTER_DeferredColor_Specular = 11,
1498         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1499         D3DPSREGISTER_DeferredMod_Specular = 13,
1500         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1501         D3DPSREGISTER_EyePosition = 15, // unused
1502         D3DPSREGISTER_FogColor = 16,
1503         D3DPSREGISTER_FogHeightFade = 17,
1504         D3DPSREGISTER_FogPlane = 18,
1505         D3DPSREGISTER_FogPlaneViewDist = 19,
1506         D3DPSREGISTER_FogRangeRecip = 20,
1507         D3DPSREGISTER_LightColor = 21,
1508         D3DPSREGISTER_LightDir = 22, // unused
1509         D3DPSREGISTER_LightPosition = 23,
1510         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1511         D3DPSREGISTER_PixelSize = 25,
1512         D3DPSREGISTER_ReflectColor = 26,
1513         D3DPSREGISTER_ReflectFactor = 27,
1514         D3DPSREGISTER_ReflectOffset = 28,
1515         D3DPSREGISTER_RefractColor = 29,
1516         D3DPSREGISTER_Saturation = 30,
1517         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1518         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1519         D3DPSREGISTER_ScreenToDepth = 33,
1520         D3DPSREGISTER_ShadowMap_Parameters = 34,
1521         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1522         D3DPSREGISTER_SpecularPower = 36,
1523         D3DPSREGISTER_UserVec1 = 37,
1524         D3DPSREGISTER_UserVec2 = 38,
1525         D3DPSREGISTER_UserVec3 = 39,
1526         D3DPSREGISTER_UserVec4 = 40,
1527         D3DPSREGISTER_ViewTintColor = 41,
1528         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1529         D3DPSREGISTER_BloomColorSubtract = 43,
1530         D3DPSREGISTER_ViewToLight = 44, // float4x4
1531         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1532         D3DPSREGISTER_NormalmapScrollBlend = 52,
1533         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1534         D3DPSREGISTER_OffsetMapping_Bias = 54,
1535         // next at 54
1536 }
1537 D3DPSREGISTER_t;
1538
1539 /// information about each possible shader permutation
1540 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1541 /// currently selected permutation
1542 r_hlsl_permutation_t *r_hlsl_permutation;
1543 /// storage for permutations linked in the hash table
1544 memexpandablearray_t r_hlsl_permutationarray;
1545
1546 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1547 {
1548         //unsigned int hashdepth = 0;
1549         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1550         r_hlsl_permutation_t *p;
1551         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1552         {
1553                 if (p->mode == mode && p->permutation == permutation)
1554                 {
1555                         //if (hashdepth > 10)
1556                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1557                         return p;
1558                 }
1559                 //hashdepth++;
1560         }
1561         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1562         p->mode = mode;
1563         p->permutation = permutation;
1564         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1565         r_hlsl_permutationhash[mode][hashindex] = p;
1566         //if (hashdepth > 10)
1567         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1568         return p;
1569 }
1570
1571 #include <d3dx9.h>
1572 //#include <d3dx9shader.h>
1573 //#include <d3dx9mesh.h>
1574
1575 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1576 {
1577         DWORD *vsbin = NULL;
1578         DWORD *psbin = NULL;
1579         fs_offset_t vsbinsize;
1580         fs_offset_t psbinsize;
1581 //      IDirect3DVertexShader9 *vs = NULL;
1582 //      IDirect3DPixelShader9 *ps = NULL;
1583         ID3DXBuffer *vslog = NULL;
1584         ID3DXBuffer *vsbuffer = NULL;
1585         ID3DXConstantTable *vsconstanttable = NULL;
1586         ID3DXBuffer *pslog = NULL;
1587         ID3DXBuffer *psbuffer = NULL;
1588         ID3DXConstantTable *psconstanttable = NULL;
1589         int vsresult = 0;
1590         int psresult = 0;
1591         char temp[MAX_INPUTLINE];
1592         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1593         char vabuf[1024];
1594         qboolean debugshader = gl_paranoid.integer != 0;
1595         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (!debugshader)
1598         {
1599                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1600                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1601         }
1602         if ((!vsbin && vertstring) || (!psbin && fragstring))
1603         {
1604                 const char* dllnames_d3dx9 [] =
1605                 {
1606                         "d3dx9_43.dll",
1607                         "d3dx9_42.dll",
1608                         "d3dx9_41.dll",
1609                         "d3dx9_40.dll",
1610                         "d3dx9_39.dll",
1611                         "d3dx9_38.dll",
1612                         "d3dx9_37.dll",
1613                         "d3dx9_36.dll",
1614                         "d3dx9_35.dll",
1615                         "d3dx9_34.dll",
1616                         "d3dx9_33.dll",
1617                         "d3dx9_32.dll",
1618                         "d3dx9_31.dll",
1619                         "d3dx9_30.dll",
1620                         "d3dx9_29.dll",
1621                         "d3dx9_28.dll",
1622                         "d3dx9_27.dll",
1623                         "d3dx9_26.dll",
1624                         "d3dx9_25.dll",
1625                         "d3dx9_24.dll",
1626                         NULL
1627                 };
1628                 dllhandle_t d3dx9_dll = NULL;
1629                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1630                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1631                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1632                 dllfunction_t d3dx9_dllfuncs[] =
1633                 {
1634                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1635                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1636                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1637                         {NULL, NULL}
1638                 };
1639                 // 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...
1640 #ifndef ID3DXBuffer_GetBufferPointer
1641 #if !defined(__cplusplus) || defined(CINTERFACE)
1642 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1643 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1644 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1645 #else
1646 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1647 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1648 #define ID3DXBuffer_Release(p)            (p)->Release()
1649 #endif
1650 #endif
1651                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1652                 {
1653                         DWORD shaderflags = 0;
1654                         if (debugshader)
1655                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1656                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1657                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1658                         if (vertstring && vertstring[0])
1659                         {
1660                                 if (debugshader)
1661                                 {
1662                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1663                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1664                                 }
1665                                 else
1666                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1667                                 if (vsbuffer)
1668                                 {
1669                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1670                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1671                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1672                                         ID3DXBuffer_Release(vsbuffer);
1673                                 }
1674                                 if (vslog)
1675                                 {
1676                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1677                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1678                                         ID3DXBuffer_Release(vslog);
1679                                 }
1680                         }
1681                         if (fragstring && fragstring[0])
1682                         {
1683                                 if (debugshader)
1684                                 {
1685                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1686                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1687                                 }
1688                                 else
1689                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1690                                 if (psbuffer)
1691                                 {
1692                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1693                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1694                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1695                                         ID3DXBuffer_Release(psbuffer);
1696                                 }
1697                                 if (pslog)
1698                                 {
1699                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1700                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1701                                         ID3DXBuffer_Release(pslog);
1702                                 }
1703                         }
1704                         Sys_UnloadLibrary(&d3dx9_dll);
1705                 }
1706                 else
1707                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1708         }
1709         if (vsbin && psbin)
1710         {
1711                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1712                 if (FAILED(vsresult))
1713                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1714                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1715                 if (FAILED(psresult))
1716                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1717         }
1718         // free the shader data
1719         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1720         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1721 }
1722
1723 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1724 {
1725         int i;
1726         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1727         int vertstring_length = 0;
1728         int geomstring_length = 0;
1729         int fragstring_length = 0;
1730         char *t;
1731         char *sourcestring;
1732         char *vertstring, *geomstring, *fragstring;
1733         char permutationname[256];
1734         char cachename[256];
1735         int vertstrings_count = 0;
1736         int geomstrings_count = 0;
1737         int fragstrings_count = 0;
1738         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741
1742         if (p->compiled)
1743                 return;
1744         p->compiled = true;
1745         p->vertexshader = NULL;
1746         p->pixelshader = NULL;
1747
1748         permutationname[0] = 0;
1749         cachename[0] = 0;
1750         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1751
1752         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1753         strlcat(cachename, "hlsl/", sizeof(cachename));
1754
1755         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1756         vertstrings_count = 0;
1757         geomstrings_count = 0;
1758         fragstrings_count = 0;
1759         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1760         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1761         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1762
1763         // the first pretext is which type of shader to compile as
1764         // (later these will all be bound together as a program object)
1765         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1766         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1767         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1768
1769         // the second pretext is the mode (for example a light source)
1770         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1771         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1772         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1773         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1774         strlcat(cachename, modeinfo->name, sizeof(cachename));
1775
1776         // now add all the permutation pretexts
1777         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778         {
1779                 if (permutation & (1ll<<i))
1780                 {
1781                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1782                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1785                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1786                 }
1787                 else
1788                 {
1789                         // keep line numbers correct
1790                         vertstrings_list[vertstrings_count++] = "\n";
1791                         geomstrings_list[geomstrings_count++] = "\n";
1792                         fragstrings_list[fragstrings_count++] = "\n";
1793                 }
1794         }
1795
1796         // add static parms
1797         R_CompileShader_AddStaticParms(mode, permutation);
1798         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1799         vertstrings_count += shaderstaticparms_count;
1800         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1801         geomstrings_count += shaderstaticparms_count;
1802         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1803         fragstrings_count += shaderstaticparms_count;
1804
1805         // replace spaces in the cachename with _ characters
1806         for (i = 0;cachename[i];i++)
1807                 if (cachename[i] == ' ')
1808                         cachename[i] = '_';
1809
1810         // now append the shader text itself
1811         vertstrings_list[vertstrings_count++] = sourcestring;
1812         geomstrings_list[geomstrings_count++] = sourcestring;
1813         fragstrings_list[fragstrings_count++] = sourcestring;
1814
1815         vertstring_length = 0;
1816         for (i = 0;i < vertstrings_count;i++)
1817                 vertstring_length += (int)strlen(vertstrings_list[i]);
1818         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1819         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1820                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1821
1822         geomstring_length = 0;
1823         for (i = 0;i < geomstrings_count;i++)
1824                 geomstring_length += (int)strlen(geomstrings_list[i]);
1825         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1826         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1827                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1828
1829         fragstring_length = 0;
1830         for (i = 0;i < fragstrings_count;i++)
1831                 fragstring_length += (int)strlen(fragstrings_list[i]);
1832         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1833         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1834                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1835
1836         // try to load the cached shader, or generate one
1837         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1838
1839         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1840                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1841         else
1842                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1843
1844         // free the strings
1845         if (vertstring)
1846                 Mem_Free(vertstring);
1847         if (geomstring)
1848                 Mem_Free(geomstring);
1849         if (fragstring)
1850                 Mem_Free(fragstring);
1851         if (sourcestring)
1852                 Mem_Free(sourcestring);
1853 }
1854
1855 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 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);}
1858 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);}
1859 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);}
1860 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);}
1861
1862 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1863 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1864 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);}
1865 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);}
1866 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);}
1867 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);}
1868
1869 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1870 {
1871         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1872         if (r_hlsl_permutation != perm)
1873         {
1874                 r_hlsl_permutation = perm;
1875                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876                 {
1877                         if (!r_hlsl_permutation->compiled)
1878                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1879                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1880                         {
1881                                 // remove features until we find a valid permutation
1882                                 int i;
1883                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884                                 {
1885                                         // reduce i more quickly whenever it would not remove any bits
1886                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1887                                         if (!(permutation & j))
1888                                                 continue;
1889                                         permutation -= j;
1890                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891                                         if (!r_hlsl_permutation->compiled)
1892                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1893                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1894                                                 break;
1895                                 }
1896                                 if (i >= SHADERPERMUTATION_COUNT)
1897                                 {
1898                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1899                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1900                                         return; // no bit left to clear, entire mode is broken
1901                                 }
1902                         }
1903                 }
1904                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1905                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1906         }
1907         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1909         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1910 }
1911 #endif
1912
1913 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1914 {
1915         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1916         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1918         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1919 }
1920
1921 void R_GLSL_Restart_f(void)
1922 {
1923         unsigned int i, limit;
1924         switch(vid.renderpath)
1925         {
1926         case RENDERPATH_D3D9:
1927 #ifdef SUPPORTD3D
1928                 {
1929                         r_hlsl_permutation_t *p;
1930                         r_hlsl_permutation = NULL;
1931                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1932                         for (i = 0;i < limit;i++)
1933                         {
1934                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1935                                 {
1936                                         if (p->vertexshader)
1937                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1938                                         if (p->pixelshader)
1939                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1940                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1941                                 }
1942                         }
1943                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1944                 }
1945 #endif
1946                 break;
1947         case RENDERPATH_D3D10:
1948                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949                 break;
1950         case RENDERPATH_D3D11:
1951                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_GL20:
1954         case RENDERPATH_GLES2:
1955                 {
1956                         r_glsl_permutation_t *p;
1957                         r_glsl_permutation = NULL;
1958                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1959                         for (i = 0;i < limit;i++)
1960                         {
1961                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1962                                 {
1963                                         GL_Backend_FreeProgram(p->program);
1964                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1965                                 }
1966                         }
1967                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1968                 }
1969                 break;
1970         case RENDERPATH_GL11:
1971         case RENDERPATH_GL13:
1972         case RENDERPATH_GLES1:
1973                 break;
1974         case RENDERPATH_SOFT:
1975                 break;
1976         }
1977 }
1978
1979 static void R_GLSL_DumpShader_f(void)
1980 {
1981         int i, language, mode, dupe;
1982         char *text;
1983         shadermodeinfo_t *modeinfo;
1984         qfile_t *file;
1985
1986         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1987         {
1988                 modeinfo = shadermodeinfo[language];
1989                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1990                 {
1991                         // don't dump the same file multiple times (most or all shaders come from the same file)
1992                         for (dupe = mode - 1;dupe >= 0;dupe--)
1993                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1994                                         break;
1995                         if (dupe >= 0)
1996                                 continue;
1997                         text = modeinfo[mode].builtinstring;
1998                         if (!text)
1999                                 continue;
2000                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2001                         if (file)
2002                         {
2003                                 FS_Print(file, "/* The engine may define the following macros:\n");
2004                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2005                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2006                                         FS_Print(file, modeinfo[i].pretext);
2007                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2008                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2009                                 FS_Print(file, "*/\n");
2010                                 FS_Print(file, text);
2011                                 FS_Close(file);
2012                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2013                         }
2014                         else
2015                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2016                 }
2017         }
2018 }
2019
2020 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2021 {
2022         dpuint64 permutation = 0;
2023         if (r_trippy.integer && !notrippy)
2024                 permutation |= SHADERPERMUTATION_TRIPPY;
2025         permutation |= SHADERPERMUTATION_VIEWTINT;
2026         if (first)
2027                 permutation |= SHADERPERMUTATION_DIFFUSE;
2028         if (second)
2029                 permutation |= SHADERPERMUTATION_SPECULAR;
2030         if (texturemode == GL_MODULATE)
2031                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2032         else if (texturemode == GL_ADD)
2033                 permutation |= SHADERPERMUTATION_GLOW;
2034         else if (texturemode == GL_DECAL)
2035                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2036         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2037                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2038         if (suppresstexalpha)
2039                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2040         if (!second)
2041                 texturemode = GL_MODULATE;
2042         if (vid.allowalphatocoverage)
2043                 GL_AlphaToCoverage(false);
2044         switch (vid.renderpath)
2045         {
2046         case RENDERPATH_D3D9:
2047 #ifdef SUPPORTD3D
2048                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2049                 R_Mesh_TexBind(GL20TU_FIRST , first );
2050                 R_Mesh_TexBind(GL20TU_SECOND, second);
2051                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2052                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2053 #endif
2054                 break;
2055         case RENDERPATH_D3D10:
2056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057                 break;
2058         case RENDERPATH_D3D11:
2059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060                 break;
2061         case RENDERPATH_GL20:
2062         case RENDERPATH_GLES2:
2063                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2064                 if (r_glsl_permutation->tex_Texture_First >= 0)
2065                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2066                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2067                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2068                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2069                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2070                 break;
2071         case RENDERPATH_GL13:
2072         case RENDERPATH_GLES1:
2073                 R_Mesh_TexBind(0, first );
2074                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2075                 R_Mesh_TexMatrix(0, NULL);
2076                 R_Mesh_TexBind(1, second);
2077                 if (second)
2078                 {
2079                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2080                         R_Mesh_TexMatrix(1, NULL);
2081                 }
2082                 break;
2083         case RENDERPATH_GL11:
2084                 R_Mesh_TexBind(0, first );
2085                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2086                 R_Mesh_TexMatrix(0, NULL);
2087                 break;
2088         case RENDERPATH_SOFT:
2089                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2090                 R_Mesh_TexBind(GL20TU_FIRST , first );
2091                 R_Mesh_TexBind(GL20TU_SECOND, second);
2092                 break;
2093         }
2094 }
2095
2096 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2097 {
2098         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2099 }
2100
2101 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2102 {
2103         dpuint64 permutation = 0;
2104         if (r_trippy.integer && !notrippy)
2105                 permutation |= SHADERPERMUTATION_TRIPPY;
2106         if (depthrgb)
2107                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2108         if (skeletal)
2109                 permutation |= SHADERPERMUTATION_SKELETAL;
2110
2111         if (vid.allowalphatocoverage)
2112                 GL_AlphaToCoverage(false);
2113         switch (vid.renderpath)
2114         {
2115         case RENDERPATH_D3D9:
2116 #ifdef SUPPORTD3D
2117                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2118 #endif
2119                 break;
2120         case RENDERPATH_D3D10:
2121                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2122                 break;
2123         case RENDERPATH_D3D11:
2124                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2125                 break;
2126         case RENDERPATH_GL20:
2127         case RENDERPATH_GLES2:
2128                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2130                 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);
2131 #endif
2132                 break;
2133         case RENDERPATH_GL13:
2134         case RENDERPATH_GLES1:
2135                 R_Mesh_TexBind(0, 0);
2136                 R_Mesh_TexBind(1, 0);
2137                 break;
2138         case RENDERPATH_GL11:
2139                 R_Mesh_TexBind(0, 0);
2140                 break;
2141         case RENDERPATH_SOFT:
2142                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2143                 break;
2144         }
2145 }
2146
2147 extern qboolean r_shadow_usingdeferredprepass;
2148 extern rtexture_t *r_shadow_attenuationgradienttexture;
2149 extern rtexture_t *r_shadow_attenuation2dtexture;
2150 extern rtexture_t *r_shadow_attenuation3dtexture;
2151 extern qboolean r_shadow_usingshadowmap2d;
2152 extern qboolean r_shadow_usingshadowmaportho;
2153 extern float r_shadow_modelshadowmap_texturescale[4];
2154 extern float r_shadow_modelshadowmap_parameters[4];
2155 extern float r_shadow_lightshadowmap_texturescale[4];
2156 extern float r_shadow_lightshadowmap_parameters[4];
2157 extern qboolean r_shadow_shadowmapvsdct;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2160 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2161 extern matrix4x4_t r_shadow_shadowmapmatrix;
2162 extern int r_shadow_prepass_width;
2163 extern int r_shadow_prepass_height;
2164 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2165 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2166 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2167 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2168
2169 #define BLENDFUNC_ALLOWS_COLORMOD      1
2170 #define BLENDFUNC_ALLOWS_FOG           2
2171 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2172 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2173 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2174 static int R_BlendFuncFlags(int src, int dst)
2175 {
2176         int r = 0;
2177
2178         // a blendfunc allows colormod if:
2179         // a) it can never keep the destination pixel invariant, or
2180         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2181         // this is to prevent unintended side effects from colormod
2182
2183         // a blendfunc allows fog if:
2184         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2185         // this is to prevent unintended side effects from fog
2186
2187         // these checks are the output of fogeval.pl
2188
2189         r |= BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2198         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2199         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2202         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2203         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2209         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2211
2212         return r;
2213 }
2214
2215 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2216 {
2217         // select a permutation of the lighting shader appropriate to this
2218         // combination of texture, entity, light source, and fogging, only use the
2219         // minimum features necessary to avoid wasting rendering time in the
2220         // fragment shader on features that are not being used
2221         dpuint64 permutation = 0;
2222         unsigned int mode = 0;
2223         int blendfuncflags;
2224         static float dummy_colormod[3] = {1, 1, 1};
2225         float *colormod = rsurface.colormod;
2226         float m16f[16];
2227         matrix4x4_t tempmatrix;
2228         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2229         if (r_trippy.integer && !notrippy)
2230                 permutation |= SHADERPERMUTATION_TRIPPY;
2231         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2232                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2233         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2234                 permutation |= SHADERPERMUTATION_OCCLUDE;
2235         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2236                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2237         if (rsurfacepass == RSURFPASS_BACKGROUND)
2238         {
2239                 // distorted background
2240                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2241                 {
2242                         mode = SHADERMODE_WATER;
2243                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2246                         {
2247                                 // this is the right thing to do for wateralpha
2248                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2249                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2250                         }
2251                         else
2252                         {
2253                                 // this is the right thing to do for entity alpha
2254                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                         }
2257                 }
2258                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2259                 {
2260                         mode = SHADERMODE_REFRACTION;
2261                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265                 }
2266                 else
2267                 {
2268                         mode = SHADERMODE_GENERIC;
2269                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2270                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2272                 }
2273                 if (vid.allowalphatocoverage)
2274                         GL_AlphaToCoverage(false);
2275         }
2276         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2277         {
2278                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2279                 {
2280                         switch(rsurface.texture->offsetmapping)
2281                         {
2282                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_OFF: break;
2286                         }
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290                 // normalmap (deferred prepass), may use alpha test on diffuse
2291                 mode = SHADERMODE_DEFERREDGEOMETRY;
2292                 GL_BlendFunc(GL_ONE, GL_ZERO);
2293                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2294                 if (vid.allowalphatocoverage)
2295                         GL_AlphaToCoverage(false);
2296         }
2297         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2298         {
2299                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2300                 {
2301                         switch(rsurface.texture->offsetmapping)
2302                         {
2303                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2304                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_OFF: break;
2307                         }
2308                 }
2309                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2310                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2311                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2312                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2313                 // light source
2314                 mode = SHADERMODE_LIGHTSOURCE;
2315                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2316                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2317                 if (diffusescale > 0)
2318                         permutation |= SHADERPERMUTATION_DIFFUSE;
2319                 if (specularscale > 0)
2320                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2321                 if (r_refdef.fogenabled)
2322                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323                 if (rsurface.texture->colormapping)
2324                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2325                 if (r_shadow_usingshadowmap2d)
2326                 {
2327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328                         if(r_shadow_shadowmapvsdct)
2329                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2330
2331                         if (r_shadow_shadowmap2ddepthbuffer)
2332                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2333                 }
2334                 if (rsurface.texture->reflectmasktexture)
2335                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2337                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2338                 if (vid.allowalphatocoverage)
2339                         GL_AlphaToCoverage(false);
2340         }
2341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2344                 {
2345                         switch(rsurface.texture->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2356                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2357                 // unshaded geometry (fullbright or ambient model lighting)
2358                 mode = SHADERMODE_FLATCOLOR;
2359                 ambientscale = diffusescale = specularscale = 0;
2360                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2361                         permutation |= SHADERPERMUTATION_GLOW;
2362                 if (r_refdef.fogenabled)
2363                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2364                 if (rsurface.texture->colormapping)
2365                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2366                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2367                 {
2368                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2369                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2370
2371                         if (r_shadow_shadowmap2ddepthbuffer)
2372                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375                         permutation |= SHADERPERMUTATION_REFLECTION;
2376                 if (rsurface.texture->reflectmasktexture)
2377                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2378                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2379                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2380                 // when using alphatocoverage, we don't need alphakill
2381                 if (vid.allowalphatocoverage)
2382                 {
2383                         if (r_transparent_alphatocoverage.integer)
2384                         {
2385                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2386                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2387                         }
2388                         else
2389                                 GL_AlphaToCoverage(false);
2390                 }
2391         }
2392         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2393         {
2394                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2395                 {
2396                         switch(rsurface.texture->offsetmapping)
2397                         {
2398                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2399                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2400                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2401                         case OFFSETMAPPING_OFF: break;
2402                         }
2403                 }
2404                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2405                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2406                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2407                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2408                 // directional model lighting
2409                 mode = SHADERMODE_LIGHTDIRECTION;
2410                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2411                         permutation |= SHADERPERMUTATION_GLOW;
2412                 permutation |= SHADERPERMUTATION_DIFFUSE;
2413                 if (specularscale > 0)
2414                         permutation |= SHADERPERMUTATION_SPECULAR;
2415                 if (r_refdef.fogenabled)
2416                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2417                 if (rsurface.texture->colormapping)
2418                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2419                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2420                 {
2421                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2422                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2423
2424                         if (r_shadow_shadowmap2ddepthbuffer)
2425                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2426                 }
2427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2428                         permutation |= SHADERPERMUTATION_REFLECTION;
2429                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2430                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2431                 if (rsurface.texture->reflectmasktexture)
2432                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2433                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2434                 {
2435                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2436                         if (r_shadow_bouncegrid_state.directional)
2437                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2438                 }
2439                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2440                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2441                 // when using alphatocoverage, we don't need alphakill
2442                 if (vid.allowalphatocoverage)
2443                 {
2444                         if (r_transparent_alphatocoverage.integer)
2445                         {
2446                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2447                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2448                         }
2449                         else
2450                                 GL_AlphaToCoverage(false);
2451                 }
2452         }
2453         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2454         {
2455                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2456                 {
2457                         switch(rsurface.texture->offsetmapping)
2458                         {
2459                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2460                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2461                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2462                         case OFFSETMAPPING_OFF: break;
2463                         }
2464                 }
2465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2467                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2468                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2469                 // ambient model lighting
2470                 mode = SHADERMODE_LIGHTDIRECTION;
2471                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2472                         permutation |= SHADERPERMUTATION_GLOW;
2473                 if (r_refdef.fogenabled)
2474                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2475                 if (rsurface.texture->colormapping)
2476                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2477                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2478                 {
2479                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2480                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2481
2482                         if (r_shadow_shadowmap2ddepthbuffer)
2483                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2484                 }
2485                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2486                         permutation |= SHADERPERMUTATION_REFLECTION;
2487                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2488                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2489                 if (rsurface.texture->reflectmasktexture)
2490                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2491                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2492                 {
2493                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2494                         if (r_shadow_bouncegrid_state.directional)
2495                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2496                 }
2497                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2498                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2499                 // when using alphatocoverage, we don't need alphakill
2500                 if (vid.allowalphatocoverage)
2501                 {
2502                         if (r_transparent_alphatocoverage.integer)
2503                         {
2504                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2505                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2506                         }
2507                         else
2508                                 GL_AlphaToCoverage(false);
2509                 }
2510         }
2511         else
2512         {
2513                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2514                 {
2515                         switch(rsurface.texture->offsetmapping)
2516                         {
2517                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2518                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2519                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2520                         case OFFSETMAPPING_OFF: break;
2521                         }
2522                 }
2523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2524                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2525                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2526                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2527                 // lightmapped wall
2528                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2529                         permutation |= SHADERPERMUTATION_GLOW;
2530                 if (r_refdef.fogenabled)
2531                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2532                 if (rsurface.texture->colormapping)
2533                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2534                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2535                 {
2536                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2537                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2538
2539                         if (r_shadow_shadowmap2ddepthbuffer)
2540                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2541                 }
2542                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2543                         permutation |= SHADERPERMUTATION_REFLECTION;
2544                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2545                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2546                 if (rsurface.texture->reflectmasktexture)
2547                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2548                 if (FAKELIGHT_ENABLED)
2549                 {
2550                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2551                         mode = SHADERMODE_FAKELIGHT;
2552                         permutation |= SHADERPERMUTATION_DIFFUSE;
2553                         if (specularscale > 0)
2554                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2555                 }
2556                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2557                 {
2558                         // deluxemapping (light direction texture)
2559                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2560                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2561                         else
2562                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2563                         permutation |= SHADERPERMUTATION_DIFFUSE;
2564                         if (specularscale > 0)
2565                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2566                 }
2567                 else if (r_glsl_deluxemapping.integer >= 2)
2568                 {
2569                         // fake deluxemapping (uniform light direction in tangentspace)
2570                         if (rsurface.uselightmaptexture)
2571                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2572                         else
2573                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2574                         permutation |= SHADERPERMUTATION_DIFFUSE;
2575                         if (specularscale > 0)
2576                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2577                 }
2578                 else if (rsurface.uselightmaptexture)
2579                 {
2580                         // ordinary lightmapping (q1bsp, q3bsp)
2581                         mode = SHADERMODE_LIGHTMAP;
2582                 }
2583                 else
2584                 {
2585                         // ordinary vertex coloring (q3bsp)
2586                         mode = SHADERMODE_VERTEXCOLOR;
2587                 }
2588                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2589                 {
2590                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2591                         if (r_shadow_bouncegrid_state.directional)
2592                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2593                 }
2594                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2595                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2596                 // when using alphatocoverage, we don't need alphakill
2597                 if (vid.allowalphatocoverage)
2598                 {
2599                         if (r_transparent_alphatocoverage.integer)
2600                         {
2601                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2602                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2603                         }
2604                         else
2605                                 GL_AlphaToCoverage(false);
2606                 }
2607         }
2608         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2609                 colormod = dummy_colormod;
2610         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2611                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2612         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2613                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2614         switch(vid.renderpath)
2615         {
2616         case RENDERPATH_D3D9:
2617 #ifdef SUPPORTD3D
2618                 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);
2619                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2620                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2621                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2622                 if (mode == SHADERMODE_LIGHTSOURCE)
2623                 {
2624                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2625                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2626                 }
2627                 else
2628                 {
2629                         if (mode == SHADERMODE_LIGHTDIRECTION)
2630                         {
2631                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2632                         }
2633                 }
2634                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2635                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2636                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2637                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2638                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2639
2640                 if (mode == SHADERMODE_LIGHTSOURCE)
2641                 {
2642                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2643                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2644                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2645                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2646                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2647
2648                         // additive passes are only darkened by fog, not tinted
2649                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2650                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2651                 }
2652                 else
2653                 {
2654                         if (mode == SHADERMODE_FLATCOLOR)
2655                         {
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2657                         }
2658                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2659                         {
2660                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2661                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2662                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2663                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2666                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2667                         }
2668                         else
2669                         {
2670                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2671                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2672                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2673                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2674                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2675                         }
2676                         // additive passes are only darkened by fog, not tinted
2677                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2678                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2679                         else
2680                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2681                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2682                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2683                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2684                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2685                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2686                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2687                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2688                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2689                         if (mode == SHADERMODE_WATER)
2690                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2691                 }
2692                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2693                 {
2694                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2695                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2696                 }
2697                 else
2698                 {
2699                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2700                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2701                 }
2702                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2703                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2704                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2705                 if (rsurface.texture->pantstexture)
2706                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2707                 else
2708                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2709                 if (rsurface.texture->shirttexture)
2710                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2711                 else
2712                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2713                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2714                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2715                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2716                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2717                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2718                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2719                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2720                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2721                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2722                         );
2723                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2724                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2725                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2726                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2727
2728                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2729                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2730                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2731                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2732                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2733                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2734                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2735                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2736                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2737                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2738                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2739                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2740                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2741                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2742                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2743                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2744                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2745                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2746                 {
2747                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2748                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2749                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2750                 }
2751                 else
2752                 {
2753                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2754                 }
2755 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2756                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2757                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2758                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2759                 {
2760                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2761                         if (rsurface.rtlight)
2762                         {
2763                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2764                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2765                         }
2766                 }
2767 #endif
2768                 break;
2769         case RENDERPATH_D3D10:
2770                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2771                 break;
2772         case RENDERPATH_D3D11:
2773                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2774                 break;
2775         case RENDERPATH_GL20:
2776         case RENDERPATH_GLES2:
2777                 if (!vid.useinterleavedarrays)
2778                 {
2779                         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);
2780                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2781                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2782                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2783                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2784                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2785                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2786                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2787                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2788                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2789                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2790                 }
2791                 else
2792                 {
2793                         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);
2794                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2795                 }
2796                 // this has to be after RSurf_PrepareVerticesForBatch
2797                 if (rsurface.batchskeletaltransform3x4buffer)
2798                         permutation |= SHADERPERMUTATION_SKELETAL;
2799                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2800 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2801                 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);
2802 #endif
2803                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2804                 if (mode == SHADERMODE_LIGHTSOURCE)
2805                 {
2806                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2807                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2808                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2809                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2810                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2811                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2812         
2813                         // additive passes are only darkened by fog, not tinted
2814                         if (r_glsl_permutation->loc_FogColor >= 0)
2815                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2816                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2817                 }
2818                 else
2819                 {
2820                         if (mode == SHADERMODE_FLATCOLOR)
2821                         {
2822                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2823                         }
2824                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2825                         {
2826                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2827                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2828                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2829                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2830                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2831                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2832                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2833                         }
2834                         else
2835                         {
2836                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2837                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2838                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2839                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2840                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2841                         }
2842                         // additive passes are only darkened by fog, not tinted
2843                         if (r_glsl_permutation->loc_FogColor >= 0)
2844                         {
2845                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2846                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2847                                 else
2848                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2849                         }
2850                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2851                         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]);
2852                         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]);
2853                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2854                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2855                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2856                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2857                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2858                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2859                 }
2860                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2861                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2862                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2863                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2864                 {
2865                         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]);
2866                         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]);
2867                 }
2868                 else
2869                 {
2870                         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]);
2871                         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]);
2872                 }
2873
2874                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2875                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2876                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2877                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2878                 {
2879                         if (rsurface.texture->pantstexture)
2880                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2881                         else
2882                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2883                 }
2884                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2885                 {
2886                         if (rsurface.texture->shirttexture)
2887                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2888                         else
2889                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2890                 }
2891                 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]);
2892                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2893                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2894                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2895                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2896                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2897                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2898                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2899                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2900                         );
2901                 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);
2902                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2903                 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]);
2904                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2905                 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);}
2906                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2907
2908                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2909                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2910                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2911                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2912                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2913                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2914                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2915                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2916                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2917                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2918                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2919                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2920                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2921                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2922                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2923                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2924                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2925                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2926                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2927                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2928                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2929                 {
2930                         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);
2931                         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);
2932                         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);
2933                 }
2934                 else
2935                 {
2936                         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);
2937                 }
2938                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2939                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2940                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2941                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2942                 {
2943                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2944                         if (rsurface.rtlight)
2945                         {
2946                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2947                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2948                         }
2949                 }
2950                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2951                 CHECKGLERROR
2952                 break;
2953         case RENDERPATH_GL11:
2954         case RENDERPATH_GL13:
2955         case RENDERPATH_GLES1:
2956                 break;
2957         case RENDERPATH_SOFT:
2958                 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);
2959                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2960                 R_SetupShader_SetPermutationSoft(mode, permutation);
2961                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2962                 if (mode == SHADERMODE_LIGHTSOURCE)
2963                 {
2964                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2965                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2966                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2967                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2968                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2969                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2970         
2971                         // additive passes are only darkened by fog, not tinted
2972                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2973                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2974                 }
2975                 else
2976                 {
2977                         if (mode == SHADERMODE_FLATCOLOR)
2978                         {
2979                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2980                         }
2981                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2982                         {
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2984                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2986                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2989                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2990                         }
2991                         else
2992                         {
2993                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2994                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2995                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2996                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2997                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2998                         }
2999                         // additive passes are only darkened by fog, not tinted
3000                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
3001                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
3002                         else
3003                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3004                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
3005                         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]);
3006                         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]);
3007                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3008                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3009                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3010                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3011                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3012                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3013                 }
3014                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3015                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3016                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3017                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3018                 {
3019                         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]);
3020                         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]);
3021                 }
3022                 else
3023                 {
3024                         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]);
3025                         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]);
3026                 }
3027
3028                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3029                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3030                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3031                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3032                 {
3033                         if (rsurface.texture->pantstexture)
3034                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3035                         else
3036                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3037                 }
3038                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3039                 {
3040                         if (rsurface.texture->shirttexture)
3041                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3042                         else
3043                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3044                 }
3045                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3046                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3047                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3048                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3049                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3050                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3051                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3052                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3053                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3054                         );
3055                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3056                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3057                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3058                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3059
3060                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3061                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3062                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3063                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3064                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3065                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3066                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3067                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3068                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3069                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3070                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3071                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3072                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3073                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3074                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3075                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3076                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3077                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3078                 {
3079                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3080                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3081                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3082                 }
3083                 else
3084                 {
3085                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3086                 }
3087 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3088                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3089                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3090                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3091                 {
3092                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3093                         if (rsurface.rtlight)
3094                         {
3095                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3096                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3097                         }
3098                 }
3099                 break;
3100         }
3101 }
3102
3103 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3104 {
3105         // select a permutation of the lighting shader appropriate to this
3106         // combination of texture, entity, light source, and fogging, only use the
3107         // minimum features necessary to avoid wasting rendering time in the
3108         // fragment shader on features that are not being used
3109         dpuint64 permutation = 0;
3110         unsigned int mode = 0;
3111         const float *lightcolorbase = rtlight->currentcolor;
3112         float ambientscale = rtlight->ambientscale;
3113         float diffusescale = rtlight->diffusescale;
3114         float specularscale = rtlight->specularscale;
3115         // this is the location of the light in view space
3116         vec3_t viewlightorigin;
3117         // this transforms from view space (camera) to light space (cubemap)
3118         matrix4x4_t viewtolight;
3119         matrix4x4_t lighttoview;
3120         float viewtolight16f[16];
3121         // light source
3122         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3123         if (rtlight->currentcubemap != r_texture_whitecube)
3124                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3125         if (diffusescale > 0)
3126                 permutation |= SHADERPERMUTATION_DIFFUSE;
3127         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3128                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3129         if (r_shadow_usingshadowmap2d)
3130         {
3131                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3132                 if (r_shadow_shadowmapvsdct)
3133                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3134
3135                 if (r_shadow_shadowmap2ddepthbuffer)
3136                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3137         }
3138         if (vid.allowalphatocoverage)
3139                 GL_AlphaToCoverage(false);
3140         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3141         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3142         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3143         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3144         switch(vid.renderpath)
3145         {
3146         case RENDERPATH_D3D9:
3147 #ifdef SUPPORTD3D
3148                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3149                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3150                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3151                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3152                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3153                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3154                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3155                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3156                 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);
3157                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3158                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3159
3160                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3161                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3162                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3163                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3164                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3165 #endif
3166                 break;
3167         case RENDERPATH_D3D10:
3168                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3169                 break;
3170         case RENDERPATH_D3D11:
3171                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3172                 break;
3173         case RENDERPATH_GL20:
3174         case RENDERPATH_GLES2:
3175                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3176                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3177                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3178                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3179                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3180                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3181                 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]);
3182                 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]);
3183                 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);
3184                 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]);
3185                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3186
3187                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3188                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3189                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3190                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3191                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3192                 break;
3193         case RENDERPATH_GL11:
3194         case RENDERPATH_GL13:
3195         case RENDERPATH_GLES1:
3196                 break;
3197         case RENDERPATH_SOFT:
3198                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3199                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3200                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3201                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3202                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3203                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3204                 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]);
3205                 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]);
3206                 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);
3207                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3208                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3209
3210                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3211                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3212                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3213                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3214                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3215                 break;
3216         }
3217 }
3218
3219 #define SKINFRAME_HASH 1024
3220
3221 typedef struct
3222 {
3223         unsigned int loadsequence; // incremented each level change
3224         memexpandablearray_t array;
3225         skinframe_t *hash[SKINFRAME_HASH];
3226 }
3227 r_skinframe_t;
3228 r_skinframe_t r_skinframe;
3229
3230 void R_SkinFrame_PrepareForPurge(void)
3231 {
3232         r_skinframe.loadsequence++;
3233         // wrap it without hitting zero
3234         if (r_skinframe.loadsequence >= 200)
3235                 r_skinframe.loadsequence = 1;
3236 }
3237
3238 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3239 {
3240         if (!skinframe)
3241                 return;
3242         // mark the skinframe as used for the purging code
3243         skinframe->loadsequence = r_skinframe.loadsequence;
3244 }
3245
3246 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3247 {
3248         if (s->merged == s->base)
3249                 s->merged = NULL;
3250         R_PurgeTexture(s->stain); s->stain = NULL;
3251         R_PurgeTexture(s->merged); s->merged = NULL;
3252         R_PurgeTexture(s->base); s->base = NULL;
3253         R_PurgeTexture(s->pants); s->pants = NULL;
3254         R_PurgeTexture(s->shirt); s->shirt = NULL;
3255         R_PurgeTexture(s->nmap); s->nmap = NULL;
3256         R_PurgeTexture(s->gloss); s->gloss = NULL;
3257         R_PurgeTexture(s->glow); s->glow = NULL;
3258         R_PurgeTexture(s->fog); s->fog = NULL;
3259         R_PurgeTexture(s->reflect); s->reflect = NULL;
3260         s->loadsequence = 0;
3261 }
3262
3263 void R_SkinFrame_Purge(void)
3264 {
3265         int i;
3266         skinframe_t *s;
3267         for (i = 0;i < SKINFRAME_HASH;i++)
3268         {
3269                 for (s = r_skinframe.hash[i];s;s = s->next)
3270                 {
3271                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3272                                 R_SkinFrame_PurgeSkinFrame(s);
3273                 }
3274         }
3275 }
3276
3277 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3278         skinframe_t *item;
3279         char basename[MAX_QPATH];
3280
3281         Image_StripImageExtension(name, basename, sizeof(basename));
3282
3283         if( last == NULL ) {
3284                 int hashindex;
3285                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3286                 item = r_skinframe.hash[hashindex];
3287         } else {
3288                 item = last->next;
3289         }
3290
3291         // linearly search through the hash bucket
3292         for( ; item ; item = item->next ) {
3293                 if( !strcmp( item->basename, basename ) ) {
3294                         return item;
3295                 }
3296         }
3297         return NULL;
3298 }
3299
3300 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3301 {
3302         skinframe_t *item;
3303         int hashindex;
3304         char basename[MAX_QPATH];
3305
3306         Image_StripImageExtension(name, basename, sizeof(basename));
3307
3308         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3309         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3310                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3311                         break;
3312
3313         if (!item) {
3314                 rtexture_t *dyntexture;
3315                 // check whether its a dynamic texture
3316                 dyntexture = CL_GetDynTexture( basename );
3317                 if (!add && !dyntexture)
3318                         return NULL;
3319                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3320                 memset(item, 0, sizeof(*item));
3321                 strlcpy(item->basename, basename, sizeof(item->basename));
3322                 item->base = dyntexture; // either NULL or dyntexture handle
3323                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3324                 item->comparewidth = comparewidth;
3325                 item->compareheight = compareheight;
3326                 item->comparecrc = comparecrc;
3327                 item->next = r_skinframe.hash[hashindex];
3328                 r_skinframe.hash[hashindex] = item;
3329         }
3330         else if (textureflags & TEXF_FORCE_RELOAD)
3331         {
3332                 rtexture_t *dyntexture;
3333                 // check whether its a dynamic texture
3334                 dyntexture = CL_GetDynTexture( basename );
3335                 if (!add && !dyntexture)
3336                         return NULL;
3337                 R_SkinFrame_PurgeSkinFrame(item);
3338         }
3339         else if( item->base == NULL )
3340         {
3341                 rtexture_t *dyntexture;
3342                 // check whether its a dynamic texture
3343                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3344                 dyntexture = CL_GetDynTexture( basename );
3345                 item->base = dyntexture; // either NULL or dyntexture handle
3346         }
3347
3348         R_SkinFrame_MarkUsed(item);
3349         return item;
3350 }
3351
3352 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3353         { \
3354                 unsigned long long avgcolor[5], wsum; \
3355                 int pix, comp, w; \
3356                 avgcolor[0] = 0; \
3357                 avgcolor[1] = 0; \
3358                 avgcolor[2] = 0; \
3359                 avgcolor[3] = 0; \
3360                 avgcolor[4] = 0; \
3361                 wsum = 0; \
3362                 for(pix = 0; pix < cnt; ++pix) \
3363                 { \
3364                         w = 0; \
3365                         for(comp = 0; comp < 3; ++comp) \
3366                                 w += getpixel; \
3367                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3368                         { \
3369                                 ++wsum; \
3370                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3371                                 w = getpixel; \
3372                                 for(comp = 0; comp < 3; ++comp) \
3373                                         avgcolor[comp] += getpixel * w; \
3374                                 avgcolor[3] += w; \
3375                         } \
3376                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3377                         avgcolor[4] += getpixel; \
3378                 } \
3379                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3380                         avgcolor[3] = 1; \
3381                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3382                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3383                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3384                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3385         }
3386
3387 extern cvar_t gl_picmip;
3388 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3389 {
3390         int j;
3391         unsigned char *pixels;
3392         unsigned char *bumppixels;
3393         unsigned char *basepixels = NULL;
3394         int basepixels_width = 0;
3395         int basepixels_height = 0;
3396         skinframe_t *skinframe;
3397         rtexture_t *ddsbase = NULL;
3398         qboolean ddshasalpha = false;
3399         float ddsavgcolor[4];
3400         char basename[MAX_QPATH];
3401         int miplevel = R_PicmipForFlags(textureflags);
3402         int savemiplevel = miplevel;
3403         int mymiplevel;
3404         char vabuf[1024];
3405
3406         if (cls.state == ca_dedicated)
3407                 return NULL;
3408
3409         // return an existing skinframe if already loaded
3410         // if loading of the first image fails, don't make a new skinframe as it
3411         // would cause all future lookups of this to be missing
3412         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3413         if (skinframe && skinframe->base)
3414                 return skinframe;
3415
3416         Image_StripImageExtension(name, basename, sizeof(basename));
3417
3418         // check for DDS texture file first
3419         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3420         {
3421                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3422                 if (basepixels == NULL)
3423                         return NULL;
3424         }
3425
3426         // FIXME handle miplevel
3427
3428         if (developer_loading.integer)
3429                 Con_Printf("loading skin \"%s\"\n", name);
3430
3431         // we've got some pixels to store, so really allocate this new texture now
3432         if (!skinframe)
3433                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3434         textureflags &= ~TEXF_FORCE_RELOAD;
3435         skinframe->stain = NULL;
3436         skinframe->merged = NULL;
3437         skinframe->base = NULL;
3438         skinframe->pants = NULL;
3439         skinframe->shirt = NULL;
3440         skinframe->nmap = NULL;
3441         skinframe->gloss = NULL;
3442         skinframe->glow = NULL;
3443         skinframe->fog = NULL;
3444         skinframe->reflect = NULL;
3445         skinframe->hasalpha = false;
3446         // we could store the q2animname here too
3447
3448         if (ddsbase)
3449         {
3450                 skinframe->base = ddsbase;
3451                 skinframe->hasalpha = ddshasalpha;
3452                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3453                 if (r_loadfog && skinframe->hasalpha)
3454                         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);
3455                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3456         }
3457         else
3458         {
3459                 basepixels_width = image_width;
3460                 basepixels_height = image_height;
3461                 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);
3462                 if (textureflags & TEXF_ALPHA)
3463                 {
3464                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3465                         {
3466                                 if (basepixels[j] < 255)
3467                                 {
3468                                         skinframe->hasalpha = true;
3469                                         break;
3470                                 }
3471                         }
3472                         if (r_loadfog && skinframe->hasalpha)
3473                         {
3474                                 // has transparent pixels
3475                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3476                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3477                                 {
3478                                         pixels[j+0] = 255;
3479                                         pixels[j+1] = 255;
3480                                         pixels[j+2] = 255;
3481                                         pixels[j+3] = basepixels[j+3];
3482                                 }
3483                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3484                                 Mem_Free(pixels);
3485                         }
3486                 }
3487                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3488 #ifndef USE_GLES2
3489                 //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]);
3490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3491                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3492                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3493                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3494 #endif
3495         }
3496
3497         if (r_loaddds)
3498         {
3499                 mymiplevel = savemiplevel;
3500                 if (r_loadnormalmap)
3501                         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);
3502                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3503                 if (r_loadgloss)
3504                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3505                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3506                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3507                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3508         }
3509
3510         // _norm is the name used by tenebrae and has been adopted as standard
3511         if (r_loadnormalmap && skinframe->nmap == NULL)
3512         {
3513                 mymiplevel = savemiplevel;
3514                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3515                 {
3516                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3517                         Mem_Free(pixels);
3518                         pixels = NULL;
3519                 }
3520                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3521                 {
3522                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3523                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3524                         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);
3525                         Mem_Free(pixels);
3526                         Mem_Free(bumppixels);
3527                 }
3528                 else if (r_shadow_bumpscale_basetexture.value > 0)
3529                 {
3530                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3531                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3532                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3533                         Mem_Free(pixels);
3534                 }
3535 #ifndef USE_GLES2
3536                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3537                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3538 #endif
3539         }
3540
3541         // _luma is supported only for tenebrae compatibility
3542         // _glow is the preferred name
3543         mymiplevel = savemiplevel;
3544         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))))
3545         {
3546                 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);
3547 #ifndef USE_GLES2
3548                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3549                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3550 #endif
3551                 Mem_Free(pixels);pixels = NULL;
3552         }
3553
3554         mymiplevel = savemiplevel;
3555         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3556         {
3557                 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);
3558 #ifndef USE_GLES2
3559                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3560                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3561 #endif
3562                 Mem_Free(pixels);
3563                 pixels = NULL;
3564         }
3565
3566         mymiplevel = savemiplevel;
3567         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3568         {
3569                 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);
3570 #ifndef USE_GLES2
3571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3572                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3573 #endif
3574                 Mem_Free(pixels);
3575                 pixels = NULL;
3576         }
3577
3578         mymiplevel = savemiplevel;
3579         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3580         {
3581                 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);
3582 #ifndef USE_GLES2
3583                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3584                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3585 #endif
3586                 Mem_Free(pixels);
3587                 pixels = NULL;
3588         }
3589
3590         mymiplevel = savemiplevel;
3591         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3592         {
3593                 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);
3594 #ifndef USE_GLES2
3595                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3596                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3597 #endif
3598                 Mem_Free(pixels);
3599                 pixels = NULL;
3600         }
3601
3602         if (basepixels)
3603                 Mem_Free(basepixels);
3604
3605         return skinframe;
3606 }
3607
3608 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3609 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3610 {
3611         int i;
3612         skinframe_t *skinframe;
3613         char vabuf[1024];
3614
3615         if (cls.state == ca_dedicated)
3616                 return NULL;
3617
3618         // if already loaded just return it, otherwise make a new skinframe
3619         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3620         if (skinframe->base)
3621                 return skinframe;
3622         textureflags &= ~TEXF_FORCE_RELOAD;
3623
3624         skinframe->stain = NULL;
3625         skinframe->merged = NULL;
3626         skinframe->base = NULL;
3627         skinframe->pants = NULL;
3628         skinframe->shirt = NULL;
3629         skinframe->nmap = NULL;
3630         skinframe->gloss = NULL;
3631         skinframe->glow = NULL;
3632         skinframe->fog = NULL;
3633         skinframe->reflect = NULL;
3634         skinframe->hasalpha = false;
3635
3636         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3637         if (!skindata)
3638                 return NULL;
3639
3640         if (developer_loading.integer)
3641                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3642
3643         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3644         {
3645                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3646                 unsigned char *b = a + width * height * 4;
3647                 Image_HeightmapToNormalmap_BGRA(skindata, 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, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3649                 Mem_Free(a);
3650         }
3651         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3652         if (textureflags & TEXF_ALPHA)
3653         {
3654                 for (i = 3;i < width * height * 4;i += 4)
3655                 {
3656                         if (skindata[i] < 255)
3657                         {
3658                                 skinframe->hasalpha = true;
3659                                 break;
3660                         }
3661                 }
3662                 if (r_loadfog && skinframe->hasalpha)
3663                 {
3664                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3665                         memcpy(fogpixels, skindata, width * height * 4);
3666                         for (i = 0;i < width * height * 4;i += 4)
3667                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3668                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3669                         Mem_Free(fogpixels);
3670                 }
3671         }
3672
3673         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3674         //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]);
3675
3676         return skinframe;
3677 }
3678
3679 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3680 {
3681         int i;
3682         int featuresmask;
3683         skinframe_t *skinframe;
3684
3685         if (cls.state == ca_dedicated)
3686                 return NULL;
3687
3688         // if already loaded just return it, otherwise make a new skinframe
3689         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3690         if (skinframe->base)
3691                 return skinframe;
3692         //textureflags &= ~TEXF_FORCE_RELOAD;
3693
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3707         if (!skindata)
3708                 return NULL;
3709
3710         if (developer_loading.integer)
3711                 Con_Printf("loading quake skin \"%s\"\n", name);
3712
3713         // 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)
3714         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3715         memcpy(skinframe->qpixels, skindata, width*height);
3716         skinframe->qwidth = width;
3717         skinframe->qheight = height;
3718
3719         featuresmask = 0;
3720         for (i = 0;i < width * height;i++)
3721                 featuresmask |= palette_featureflags[skindata[i]];
3722
3723         skinframe->hasalpha = false;
3724         // fence textures
3725         if (name[0] == '{')
3726                 skinframe->hasalpha = true;
3727         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3728         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3729         skinframe->qgeneratemerged = true;
3730         skinframe->qgeneratebase = skinframe->qhascolormapping;
3731         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3732
3733         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[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
3739 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3740 {
3741         int width;
3742         int height;
3743         unsigned char *skindata;
3744         char vabuf[1024];
3745
3746         if (!skinframe->qpixels)
3747                 return;
3748
3749         if (!skinframe->qhascolormapping)
3750                 colormapped = false;
3751
3752         if (colormapped)
3753         {
3754                 if (!skinframe->qgeneratebase)
3755                         return;
3756         }
3757         else
3758         {
3759                 if (!skinframe->qgeneratemerged)
3760                         return;
3761         }
3762
3763         width = skinframe->qwidth;
3764         height = skinframe->qheight;
3765         skindata = skinframe->qpixels;
3766
3767         if (skinframe->qgeneratenmap)
3768         {
3769                 unsigned char *a, *b;
3770                 skinframe->qgeneratenmap = false;
3771                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3772                 b = a + width * height * 4;
3773                 // use either a custom palette or the quake palette
3774                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3775                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3776                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3777                 Mem_Free(a);
3778         }
3779
3780         if (skinframe->qgenerateglow)
3781         {
3782                 skinframe->qgenerateglow = false;
3783                 if (skinframe->hasalpha) // fence textures
3784                         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
3785                 else
3786                         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
3787         }
3788
3789         if (colormapped)
3790         {
3791                 skinframe->qgeneratebase = false;
3792                 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);
3793                 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);
3794                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3795         }
3796         else
3797         {
3798                 skinframe->qgeneratemerged = false;
3799                 if (skinframe->hasalpha) // fence textures
3800                         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);
3801                 else
3802                         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);
3803         }
3804
3805         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3806         {
3807                 Mem_Free(skinframe->qpixels);
3808                 skinframe->qpixels = NULL;
3809         }
3810 }
3811
3812 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)
3813 {
3814         int i;
3815         skinframe_t *skinframe;
3816         char vabuf[1024];
3817
3818         if (cls.state == ca_dedicated)
3819                 return NULL;
3820
3821         // if already loaded just return it, otherwise make a new skinframe
3822         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3823         if (skinframe->base)
3824                 return skinframe;
3825         textureflags &= ~TEXF_FORCE_RELOAD;
3826
3827         skinframe->stain = NULL;
3828         skinframe->merged = NULL;
3829         skinframe->base = NULL;
3830         skinframe->pants = NULL;
3831         skinframe->shirt = NULL;
3832         skinframe->nmap = NULL;
3833         skinframe->gloss = NULL;
3834         skinframe->glow = NULL;
3835         skinframe->fog = NULL;
3836         skinframe->reflect = NULL;
3837         skinframe->hasalpha = false;
3838
3839         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3840         if (!skindata)
3841                 return NULL;
3842
3843         if (developer_loading.integer)
3844                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3845
3846         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3847         if (textureflags & TEXF_ALPHA)
3848         {
3849                 for (i = 0;i < width * height;i++)
3850                 {
3851                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3852                         {
3853                                 skinframe->hasalpha = true;
3854                                 break;
3855                         }
3856                 }
3857                 if (r_loadfog && skinframe->hasalpha)
3858                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3859         }
3860
3861         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3862         //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]);
3863
3864         return skinframe;
3865 }
3866
3867 skinframe_t *R_SkinFrame_LoadMissing(void)
3868 {
3869         skinframe_t *skinframe;
3870
3871         if (cls.state == ca_dedicated)
3872                 return NULL;
3873
3874         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3875         skinframe->stain = NULL;
3876         skinframe->merged = NULL;
3877         skinframe->base = NULL;
3878         skinframe->pants = NULL;
3879         skinframe->shirt = NULL;
3880         skinframe->nmap = NULL;
3881         skinframe->gloss = NULL;
3882         skinframe->glow = NULL;
3883         skinframe->fog = NULL;
3884         skinframe->reflect = NULL;
3885         skinframe->hasalpha = false;
3886
3887         skinframe->avgcolor[0] = rand() / RAND_MAX;
3888         skinframe->avgcolor[1] = rand() / RAND_MAX;
3889         skinframe->avgcolor[2] = rand() / RAND_MAX;
3890         skinframe->avgcolor[3] = 1;
3891
3892         return skinframe;
3893 }
3894
3895 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3896 typedef struct suffixinfo_s
3897 {
3898         const char *suffix;
3899         qboolean flipx, flipy, flipdiagonal;
3900 }
3901 suffixinfo_t;
3902 static suffixinfo_t suffix[3][6] =
3903 {
3904         {
3905                 {"px",   false, false, false},
3906                 {"nx",   false, false, false},
3907                 {"py",   false, false, false},
3908                 {"ny",   false, false, false},
3909                 {"pz",   false, false, false},
3910                 {"nz",   false, false, false}
3911         },
3912         {
3913                 {"posx", false, false, false},
3914                 {"negx", false, false, false},
3915                 {"posy", false, false, false},
3916                 {"negy", false, false, false},
3917                 {"posz", false, false, false},
3918                 {"negz", false, false, false}
3919         },
3920         {
3921                 {"rt",    true, false,  true},
3922                 {"lf",   false,  true,  true},
3923                 {"ft",    true,  true, false},
3924                 {"bk",   false, false, false},
3925                 {"up",    true, false,  true},
3926                 {"dn",    true, false,  true}
3927         }
3928 };
3929
3930 static int componentorder[4] = {0, 1, 2, 3};
3931
3932 static rtexture_t *R_LoadCubemap(const char *basename)
3933 {
3934         int i, j, cubemapsize;
3935         unsigned char *cubemappixels, *image_buffer;
3936         rtexture_t *cubemaptexture;
3937         char name[256];
3938         // must start 0 so the first loadimagepixels has no requested width/height
3939         cubemapsize = 0;
3940         cubemappixels = NULL;
3941         cubemaptexture = NULL;
3942         // keep trying different suffix groups (posx, px, rt) until one loads
3943         for (j = 0;j < 3 && !cubemappixels;j++)
3944         {
3945                 // load the 6 images in the suffix group
3946                 for (i = 0;i < 6;i++)
3947                 {
3948                         // generate an image name based on the base and and suffix
3949                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3950                         // load it
3951                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3952                         {
3953                                 // an image loaded, make sure width and height are equal
3954                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3955                                 {
3956                                         // if this is the first image to load successfully, allocate the cubemap memory
3957                                         if (!cubemappixels && image_width >= 1)
3958                                         {
3959                                                 cubemapsize = image_width;
3960                                                 // note this clears to black, so unavailable sides are black
3961                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3962                                         }
3963                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3964                                         if (cubemappixels)
3965                                                 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);
3966                                 }
3967                                 else
3968                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3969                                 // free the image
3970                                 Mem_Free(image_buffer);
3971                         }
3972                 }
3973         }
3974         // if a cubemap loaded, upload it
3975         if (cubemappixels)
3976         {
3977                 if (developer_loading.integer)
3978                         Con_Printf("loading cubemap \"%s\"\n", basename);
3979
3980                 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);
3981                 Mem_Free(cubemappixels);
3982         }
3983         else
3984         {
3985                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3986                 if (developer_loading.integer)
3987                 {
3988                         Con_Printf("(tried tried images ");
3989                         for (j = 0;j < 3;j++)
3990                                 for (i = 0;i < 6;i++)
3991                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3992                         Con_Print(" and was unable to find any of them).\n");
3993                 }
3994         }
3995         return cubemaptexture;
3996 }
3997
3998 rtexture_t *R_GetCubemap(const char *basename)
3999 {
4000         int i;
4001         for (i = 0;i < r_texture_numcubemaps;i++)
4002                 if (r_texture_cubemaps[i] != NULL)
4003                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4004                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4005         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4006                 return r_texture_whitecube;
4007         r_texture_numcubemaps++;
4008         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4009         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4010         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4011         return r_texture_cubemaps[i]->texture;
4012 }
4013
4014 static void R_Main_FreeViewCache(void)
4015 {
4016         if (r_refdef.viewcache.entityvisible)
4017                 Mem_Free(r_refdef.viewcache.entityvisible);
4018         if (r_refdef.viewcache.world_pvsbits)
4019                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4020         if (r_refdef.viewcache.world_leafvisible)
4021                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4022         if (r_refdef.viewcache.world_surfacevisible)
4023                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4024         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4025 }
4026
4027 static void R_Main_ResizeViewCache(void)
4028 {
4029         int numentities = r_refdef.scene.numentities;
4030         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4031         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4032         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4033         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4034         if (r_refdef.viewcache.maxentities < numentities)
4035         {
4036                 r_refdef.viewcache.maxentities = numentities;
4037                 if (r_refdef.viewcache.entityvisible)
4038                         Mem_Free(r_refdef.viewcache.entityvisible);
4039                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4040         }
4041         if (r_refdef.viewcache.world_numclusters != numclusters)
4042         {
4043                 r_refdef.viewcache.world_numclusters = numclusters;
4044                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4045                 if (r_refdef.viewcache.world_pvsbits)
4046                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4047                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4048         }
4049         if (r_refdef.viewcache.world_numleafs != numleafs)
4050         {
4051                 r_refdef.viewcache.world_numleafs = numleafs;
4052                 if (r_refdef.viewcache.world_leafvisible)
4053                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4054                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4055         }
4056         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4057         {
4058                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4059                 if (r_refdef.viewcache.world_surfacevisible)
4060                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4061                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4062         }
4063 }
4064
4065 extern rtexture_t *loadingscreentexture;
4066 static void gl_main_start(void)
4067 {
4068         loadingscreentexture = NULL;
4069         r_texture_blanknormalmap = NULL;
4070         r_texture_white = NULL;
4071         r_texture_grey128 = NULL;
4072         r_texture_black = NULL;
4073         r_texture_whitecube = NULL;
4074         r_texture_normalizationcube = NULL;
4075         r_texture_fogattenuation = NULL;
4076         r_texture_fogheighttexture = NULL;
4077         r_texture_gammaramps = NULL;
4078         r_texture_numcubemaps = 0;
4079         r_uniformbufferalignment = 32;
4080
4081         r_loaddds = r_texture_dds_load.integer != 0;
4082         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4083
4084         switch(vid.renderpath)
4085         {
4086         case RENDERPATH_GL20:
4087         case RENDERPATH_D3D9:
4088         case RENDERPATH_D3D10:
4089         case RENDERPATH_D3D11:
4090         case RENDERPATH_SOFT:
4091         case RENDERPATH_GLES2:
4092                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4093                 Cvar_SetValueQuick(&gl_combine, 1);
4094                 Cvar_SetValueQuick(&r_glsl, 1);
4095                 r_loadnormalmap = true;
4096                 r_loadgloss = true;
4097                 r_loadfog = false;
4098 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4099                 if (vid.support.arb_uniform_buffer_object)
4100                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4101 #endif
4102                         break;
4103         case RENDERPATH_GL13:
4104         case RENDERPATH_GLES1:
4105                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4106                 Cvar_SetValueQuick(&gl_combine, 1);
4107                 Cvar_SetValueQuick(&r_glsl, 0);
4108                 r_loadnormalmap = false;
4109                 r_loadgloss = false;
4110                 r_loadfog = true;
4111                 break;
4112         case RENDERPATH_GL11:
4113                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4114                 Cvar_SetValueQuick(&gl_combine, 0);
4115                 Cvar_SetValueQuick(&r_glsl, 0);
4116                 r_loadnormalmap = false;
4117                 r_loadgloss = false;
4118                 r_loadfog = true;
4119                 break;
4120         }
4121
4122         R_AnimCache_Free();
4123         R_FrameData_Reset();
4124         R_BufferData_Reset();
4125
4126         r_numqueries = 0;
4127         r_maxqueries = 0;
4128         memset(r_queries, 0, sizeof(r_queries));
4129
4130         r_qwskincache = NULL;
4131         r_qwskincache_size = 0;
4132
4133         // due to caching of texture_t references, the collision cache must be reset
4134         Collision_Cache_Reset(true);
4135
4136         // set up r_skinframe loading system for textures
4137         memset(&r_skinframe, 0, sizeof(r_skinframe));
4138         r_skinframe.loadsequence = 1;
4139         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4140
4141         r_main_texturepool = R_AllocTexturePool();
4142         R_BuildBlankTextures();
4143         R_BuildNoTexture();
4144         if (vid.support.arb_texture_cube_map)
4145         {
4146                 R_BuildWhiteCube();
4147                 R_BuildNormalizationCube();
4148         }
4149         r_texture_fogattenuation = NULL;
4150         r_texture_fogheighttexture = NULL;
4151         r_texture_gammaramps = NULL;
4152         //r_texture_fogintensity = NULL;
4153         memset(&r_fb, 0, sizeof(r_fb));
4154         r_glsl_permutation = NULL;
4155         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4156         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4157 #ifdef SUPPORTD3D
4158         r_hlsl_permutation = NULL;
4159         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4160         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4161 #endif
4162         memset(&r_svbsp, 0, sizeof (r_svbsp));
4163
4164         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4165         r_texture_numcubemaps = 0;
4166
4167         r_refdef.fogmasktable_density = 0;
4168
4169 #ifdef __ANDROID__
4170         // For Steelstorm Android
4171         // FIXME CACHE the program and reload
4172         // FIXME see possible combinations for SS:BR android
4173         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4174         R_SetupShader_SetPermutationGLSL(0, 12);
4175         R_SetupShader_SetPermutationGLSL(0, 13);
4176         R_SetupShader_SetPermutationGLSL(0, 8388621);
4177         R_SetupShader_SetPermutationGLSL(3, 0);
4178         R_SetupShader_SetPermutationGLSL(3, 2048);
4179         R_SetupShader_SetPermutationGLSL(5, 0);
4180         R_SetupShader_SetPermutationGLSL(5, 2);
4181         R_SetupShader_SetPermutationGLSL(5, 2048);
4182         R_SetupShader_SetPermutationGLSL(5, 8388608);
4183         R_SetupShader_SetPermutationGLSL(11, 1);
4184         R_SetupShader_SetPermutationGLSL(11, 2049);
4185         R_SetupShader_SetPermutationGLSL(11, 8193);
4186         R_SetupShader_SetPermutationGLSL(11, 10241);
4187         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4188 #endif
4189 }
4190
4191 static void gl_main_shutdown(void)
4192 {
4193         R_AnimCache_Free();
4194         R_FrameData_Reset();
4195         R_BufferData_Reset();
4196
4197         R_Main_FreeViewCache();
4198
4199         switch(vid.renderpath)
4200         {
4201         case RENDERPATH_GL11:
4202         case RENDERPATH_GL13:
4203         case RENDERPATH_GL20:
4204         case RENDERPATH_GLES1:
4205         case RENDERPATH_GLES2:
4206 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4207                 if (r_maxqueries)
4208                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4209 #endif
4210                 break;
4211         case RENDERPATH_D3D9:
4212                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4213                 break;
4214         case RENDERPATH_D3D10:
4215                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4216                 break;
4217         case RENDERPATH_D3D11:
4218                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4219                 break;
4220         case RENDERPATH_SOFT:
4221                 break;
4222         }
4223
4224         r_numqueries = 0;
4225         r_maxqueries = 0;
4226         memset(r_queries, 0, sizeof(r_queries));
4227
4228         r_qwskincache = NULL;
4229         r_qwskincache_size = 0;
4230
4231         // clear out the r_skinframe state
4232         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4233         memset(&r_skinframe, 0, sizeof(r_skinframe));
4234
4235         if (r_svbsp.nodes)
4236                 Mem_Free(r_svbsp.nodes);
4237         memset(&r_svbsp, 0, sizeof (r_svbsp));
4238         R_FreeTexturePool(&r_main_texturepool);
4239         loadingscreentexture = NULL;
4240         r_texture_blanknormalmap = NULL;
4241         r_texture_white = NULL;
4242         r_texture_grey128 = NULL;
4243         r_texture_black = NULL;
4244         r_texture_whitecube = NULL;
4245         r_texture_normalizationcube = NULL;
4246         r_texture_fogattenuation = NULL;
4247         r_texture_fogheighttexture = NULL;
4248         r_texture_gammaramps = NULL;
4249         r_texture_numcubemaps = 0;
4250         //r_texture_fogintensity = NULL;
4251         memset(&r_fb, 0, sizeof(r_fb));
4252         R_GLSL_Restart_f();
4253
4254         r_glsl_permutation = NULL;
4255         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4256         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4257 #ifdef SUPPORTD3D
4258         r_hlsl_permutation = NULL;
4259         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4260         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4261 #endif
4262 }
4263
4264 static void gl_main_newmap(void)
4265 {
4266         // FIXME: move this code to client
4267         char *entities, entname[MAX_QPATH];
4268         if (r_qwskincache)
4269                 Mem_Free(r_qwskincache);
4270         r_qwskincache = NULL;
4271         r_qwskincache_size = 0;
4272         if (cl.worldmodel)
4273         {
4274                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4275                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4276                 {
4277                         CL_ParseEntityLump(entities);
4278                         Mem_Free(entities);
4279                         return;
4280                 }
4281                 if (cl.worldmodel->brush.entities)
4282                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4283         }
4284         R_Main_FreeViewCache();
4285
4286         R_FrameData_Reset();
4287         R_BufferData_Reset();
4288 }
4289
4290 void GL_Main_Init(void)
4291 {
4292         int i;
4293         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4294         R_InitShaderModeInfo();
4295
4296         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4297         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4298         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4299         if (gamemode == GAME_NEHAHRA)
4300         {
4301                 Cvar_RegisterVariable (&gl_fogenable);
4302                 Cvar_RegisterVariable (&gl_fogdensity);
4303                 Cvar_RegisterVariable (&gl_fogred);
4304                 Cvar_RegisterVariable (&gl_foggreen);
4305                 Cvar_RegisterVariable (&gl_fogblue);
4306                 Cvar_RegisterVariable (&gl_fogstart);
4307                 Cvar_RegisterVariable (&gl_fogend);
4308                 Cvar_RegisterVariable (&gl_skyclip);
4309         }
4310         Cvar_RegisterVariable(&r_motionblur);
4311         Cvar_RegisterVariable(&r_damageblur);
4312         Cvar_RegisterVariable(&r_motionblur_averaging);
4313         Cvar_RegisterVariable(&r_motionblur_randomize);
4314         Cvar_RegisterVariable(&r_motionblur_minblur);
4315         Cvar_RegisterVariable(&r_motionblur_maxblur);
4316         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4317         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4318         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4319         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4320         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4321         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4322         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4323         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4324         Cvar_RegisterVariable(&r_equalize_entities_by);
4325         Cvar_RegisterVariable(&r_equalize_entities_to);
4326         Cvar_RegisterVariable(&r_depthfirst);
4327         Cvar_RegisterVariable(&r_useinfinitefarclip);
4328         Cvar_RegisterVariable(&r_farclip_base);
4329         Cvar_RegisterVariable(&r_farclip_world);
4330         Cvar_RegisterVariable(&r_nearclip);
4331         Cvar_RegisterVariable(&r_deformvertexes);
4332         Cvar_RegisterVariable(&r_transparent);
4333         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4334         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4335         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4336         Cvar_RegisterVariable(&r_showoverdraw);
4337         Cvar_RegisterVariable(&r_showbboxes);
4338         Cvar_RegisterVariable(&r_showbboxes_client);
4339         Cvar_RegisterVariable(&r_showsurfaces);
4340         Cvar_RegisterVariable(&r_showtris);
4341         Cvar_RegisterVariable(&r_shownormals);
4342         Cvar_RegisterVariable(&r_showlighting);
4343         Cvar_RegisterVariable(&r_showshadowvolumes);
4344         Cvar_RegisterVariable(&r_showcollisionbrushes);
4345         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4346         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4347         Cvar_RegisterVariable(&r_showdisabledepthtest);
4348         Cvar_RegisterVariable(&r_drawportals);
4349         Cvar_RegisterVariable(&r_drawentities);
4350         Cvar_RegisterVariable(&r_draw2d);
4351         Cvar_RegisterVariable(&r_drawworld);
4352         Cvar_RegisterVariable(&r_cullentities_trace);
4353         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4354         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4355         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4356         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4357         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4358         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4359         Cvar_RegisterVariable(&r_sortentities);
4360         Cvar_RegisterVariable(&r_drawviewmodel);
4361         Cvar_RegisterVariable(&r_drawexteriormodel);
4362         Cvar_RegisterVariable(&r_speeds);
4363         Cvar_RegisterVariable(&r_fullbrights);
4364         Cvar_RegisterVariable(&r_wateralpha);
4365         Cvar_RegisterVariable(&r_dynamic);
4366         Cvar_RegisterVariable(&r_fakelight);
4367         Cvar_RegisterVariable(&r_fakelight_intensity);
4368         Cvar_RegisterVariable(&r_fullbright_directed);
4369         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4370         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4371         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4372         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4373         Cvar_RegisterVariable(&r_fullbright);
4374         Cvar_RegisterVariable(&r_shadows);
4375         Cvar_RegisterVariable(&r_shadows_darken);
4376         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4377         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4378         Cvar_RegisterVariable(&r_shadows_throwdistance);
4379         Cvar_RegisterVariable(&r_shadows_throwdirection);
4380         Cvar_RegisterVariable(&r_shadows_focus);
4381         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4382         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4383         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4384         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4385         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4386         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4387         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4388         Cvar_RegisterVariable(&r_fog_exp2);
4389         Cvar_RegisterVariable(&r_fog_clear);
4390         Cvar_RegisterVariable(&r_drawfog);
4391         Cvar_RegisterVariable(&r_transparentdepthmasking);
4392         Cvar_RegisterVariable(&r_transparent_sortmindist);
4393         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4394         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4395         Cvar_RegisterVariable(&r_texture_dds_load);
4396         Cvar_RegisterVariable(&r_texture_dds_save);
4397         Cvar_RegisterVariable(&r_textureunits);
4398         Cvar_RegisterVariable(&gl_combine);
4399         Cvar_RegisterVariable(&r_usedepthtextures);
4400         Cvar_RegisterVariable(&r_viewfbo);
4401         Cvar_RegisterVariable(&r_viewscale);
4402         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4403         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4404         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4405         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4406         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4407         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4408         Cvar_RegisterVariable(&r_glsl);
4409         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4410         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4412         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4413         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4414         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4415         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4416         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4417         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4418         Cvar_RegisterVariable(&r_glsl_postprocess);
4419         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4421         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4422         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4427         Cvar_RegisterVariable(&r_celshading);
4428         Cvar_RegisterVariable(&r_celoutlines);
4429
4430         Cvar_RegisterVariable(&r_water);
4431         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4432         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4433         Cvar_RegisterVariable(&r_water_clippingplanebias);
4434         Cvar_RegisterVariable(&r_water_refractdistort);
4435         Cvar_RegisterVariable(&r_water_reflectdistort);
4436         Cvar_RegisterVariable(&r_water_scissormode);
4437         Cvar_RegisterVariable(&r_water_lowquality);
4438         Cvar_RegisterVariable(&r_water_hideplayer);
4439         Cvar_RegisterVariable(&r_water_fbo);
4440
4441         Cvar_RegisterVariable(&r_lerpsprites);
4442         Cvar_RegisterVariable(&r_lerpmodels);
4443         Cvar_RegisterVariable(&r_lerplightstyles);
4444         Cvar_RegisterVariable(&r_waterscroll);
4445         Cvar_RegisterVariable(&r_bloom);
4446         Cvar_RegisterVariable(&r_bloom_colorscale);
4447         Cvar_RegisterVariable(&r_bloom_brighten);
4448         Cvar_RegisterVariable(&r_bloom_blur);
4449         Cvar_RegisterVariable(&r_bloom_resolution);
4450         Cvar_RegisterVariable(&r_bloom_colorexponent);
4451         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4452         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4453         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4454         Cvar_RegisterVariable(&r_hdr_glowintensity);
4455         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4457         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4458         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4459         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4460         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4461         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4462         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4463         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4464         Cvar_RegisterVariable(&developer_texturelogging);
4465         Cvar_RegisterVariable(&gl_lightmaps);
4466         Cvar_RegisterVariable(&r_test);
4467         Cvar_RegisterVariable(&r_batch_multidraw);
4468         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4469         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4470         Cvar_RegisterVariable(&r_glsl_skeletal);
4471         Cvar_RegisterVariable(&r_glsl_saturation);
4472         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4473         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4474         Cvar_RegisterVariable(&r_framedatasize);
4475         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4476                 Cvar_RegisterVariable(&r_buffermegs[i]);
4477         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4478         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4479                 Cvar_SetValue("r_fullbrights", 0);
4480 #ifdef DP_MOBILETOUCH
4481         // GLES devices have terrible depth precision in general, so...
4482         Cvar_SetValueQuick(&r_nearclip, 4);
4483         Cvar_SetValueQuick(&r_farclip_base, 4096);
4484         Cvar_SetValueQuick(&r_farclip_world, 0);
4485         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4486 #endif
4487         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4488 }
4489
4490 void Render_Init(void)
4491 {
4492         gl_backend_init();
4493         R_Textures_Init();
4494         GL_Main_Init();
4495         Font_Init();
4496         GL_Draw_Init();
4497         R_Shadow_Init();
4498         R_Sky_Init();
4499         GL_Surf_Init();
4500         Sbar_Init();
4501         R_Particles_Init();
4502         R_Explosion_Init();
4503         R_LightningBeams_Init();
4504         Mod_RenderInit();
4505 }
4506
4507 /*
4508 ===============
4509 GL_Init
4510 ===============
4511 */
4512 #ifndef USE_GLES2
4513 extern char *ENGINE_EXTENSIONS;
4514 void GL_Init (void)
4515 {
4516         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4517         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4518         gl_version = (const char *)qglGetString(GL_VERSION);
4519         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4520
4521         if (!gl_extensions)
4522                 gl_extensions = "";
4523         if (!gl_platformextensions)
4524                 gl_platformextensions = "";
4525
4526         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4527         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4528         Con_Printf("GL_VERSION: %s\n", gl_version);
4529         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4530         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4531
4532         VID_CheckExtensions();
4533
4534         // LordHavoc: report supported extensions
4535 #ifdef CONFIG_MENU
4536         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4537 #else
4538         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4539 #endif
4540
4541         // clear to black (loading plaque will be seen over this)
4542         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4543 }
4544 #endif
4545
4546 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4547 {
4548         int i;
4549         mplane_t *p;
4550         if (r_trippy.integer)
4551                 return false;
4552         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4553         {
4554                 p = r_refdef.view.frustum + i;
4555                 switch(p->signbits)
4556                 {
4557                 default:
4558                 case 0:
4559                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4560                                 return true;
4561                         break;
4562                 case 1:
4563                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 2:
4567                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 3:
4571                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 4:
4575                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 5:
4579                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 case 6:
4583                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4584                                 return true;
4585                         break;
4586                 case 7:
4587                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4588                                 return true;
4589                         break;
4590                 }
4591         }
4592         return false;
4593 }
4594
4595 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4596 {
4597         int i;
4598         const mplane_t *p;
4599         if (r_trippy.integer)
4600                 return false;
4601         for (i = 0;i < numplanes;i++)
4602         {
4603                 p = planes + i;
4604                 switch(p->signbits)
4605                 {
4606                 default:
4607                 case 0:
4608                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4609                                 return true;
4610                         break;
4611                 case 1:
4612                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4613                                 return true;
4614                         break;
4615                 case 2:
4616                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4617                                 return true;
4618                         break;
4619                 case 3:
4620                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4621                                 return true;
4622                         break;
4623                 case 4:
4624                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4625                                 return true;
4626                         break;
4627                 case 5:
4628                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4629                                 return true;
4630                         break;
4631                 case 6:
4632                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4633                                 return true;
4634                         break;
4635                 case 7:
4636                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4637                                 return true;
4638                         break;
4639                 }
4640         }
4641         return false;
4642 }
4643
4644 //==================================================================================
4645
4646 // LordHavoc: this stores temporary data used within the same frame
4647
4648 typedef struct r_framedata_mem_s
4649 {
4650         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4651         size_t size; // how much usable space
4652         size_t current; // how much space in use
4653         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4654         size_t wantedsize; // how much space was allocated
4655         unsigned char *data; // start of real data (16byte aligned)
4656 }
4657 r_framedata_mem_t;
4658
4659 static r_framedata_mem_t *r_framedata_mem;
4660
4661 void R_FrameData_Reset(void)
4662 {
4663         while (r_framedata_mem)
4664         {
4665                 r_framedata_mem_t *next = r_framedata_mem->purge;
4666                 Mem_Free(r_framedata_mem);
4667                 r_framedata_mem = next;
4668         }
4669 }
4670
4671 static void R_FrameData_Resize(qboolean mustgrow)
4672 {
4673         size_t wantedsize;
4674         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4675         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4676         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4677         {
4678                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4679                 newmem->wantedsize = wantedsize;
4680                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4681                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4682                 newmem->current = 0;
4683                 newmem->mark = 0;
4684                 newmem->purge = r_framedata_mem;
4685                 r_framedata_mem = newmem;
4686         }
4687 }
4688
4689 void R_FrameData_NewFrame(void)
4690 {
4691         R_FrameData_Resize(false);
4692         if (!r_framedata_mem)
4693                 return;
4694         // if we ran out of space on the last frame, free the old memory now
4695         while (r_framedata_mem->purge)
4696         {
4697                 // repeatedly remove the second item in the list, leaving only head
4698                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4699                 Mem_Free(r_framedata_mem->purge);
4700                 r_framedata_mem->purge = next;
4701         }
4702         // reset the current mem pointer
4703         r_framedata_mem->current = 0;
4704         r_framedata_mem->mark = 0;
4705 }
4706
4707 void *R_FrameData_Alloc(size_t size)
4708 {
4709         void *data;
4710         float newvalue;
4711
4712         // align to 16 byte boundary - the data pointer is already aligned, so we
4713         // only need to ensure the size of every allocation is also aligned
4714         size = (size + 15) & ~15;
4715
4716         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4717         {
4718                 // emergency - we ran out of space, allocate more memory
4719                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4720                 newvalue = r_framedatasize.value * 2.0f;
4721                 // 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
4722                 if (sizeof(size_t) >= 8)
4723                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4724                 else
4725                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4726                 // this might not be a growing it, but we'll allocate another buffer every time
4727                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4728                 R_FrameData_Resize(true);
4729         }
4730
4731         data = r_framedata_mem->data + r_framedata_mem->current;
4732         r_framedata_mem->current += size;
4733
4734         // count the usage for stats
4735         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4736         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4737
4738         return (void *)data;
4739 }
4740
4741 void *R_FrameData_Store(size_t size, void *data)
4742 {
4743         void *d = R_FrameData_Alloc(size);
4744         if (d && data)
4745                 memcpy(d, data, size);
4746         return d;
4747 }
4748
4749 void R_FrameData_SetMark(void)
4750 {
4751         if (!r_framedata_mem)
4752                 return;
4753         r_framedata_mem->mark = r_framedata_mem->current;
4754 }
4755
4756 void R_FrameData_ReturnToMark(void)
4757 {
4758         if (!r_framedata_mem)
4759                 return;
4760         r_framedata_mem->current = r_framedata_mem->mark;
4761 }
4762
4763 //==================================================================================
4764
4765 // avoid reusing the same buffer objects on consecutive frames
4766 #define R_BUFFERDATA_CYCLE 3
4767
4768 typedef struct r_bufferdata_buffer_s
4769 {
4770         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4771         size_t size; // how much usable space
4772         size_t current; // how much space in use
4773         r_meshbuffer_t *buffer; // the buffer itself
4774 }
4775 r_bufferdata_buffer_t;
4776
4777 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4778 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4779
4780 /// frees all dynamic buffers
4781 void R_BufferData_Reset(void)
4782 {
4783         int cycle, type;
4784         r_bufferdata_buffer_t **p, *mem;
4785         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4786         {
4787                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4788                 {
4789                         // free all buffers
4790                         p = &r_bufferdata_buffer[cycle][type];
4791                         while (*p)
4792                         {
4793                                 mem = *p;
4794                                 *p = (*p)->purge;
4795                                 if (mem->buffer)
4796                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4797                                 Mem_Free(mem);
4798                         }
4799                 }
4800         }
4801 }
4802
4803 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4804 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4805 {
4806         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4807         size_t size;
4808         float newvalue = r_buffermegs[type].value;
4809
4810         // increase the cvar if we have to (but only if we already have a mem)
4811         if (mustgrow && mem)
4812                 newvalue *= 2.0f;
4813         newvalue = bound(0.25f, newvalue, 256.0f);
4814         while (newvalue * 1024*1024 < minsize)
4815                 newvalue *= 2.0f;
4816
4817         // clamp the cvar to valid range
4818         newvalue = bound(0.25f, newvalue, 256.0f);
4819         if (r_buffermegs[type].value != newvalue)
4820                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4821
4822         // calculate size in bytes
4823         size = (size_t)(newvalue * 1024*1024);
4824         size = bound(131072, size, 256*1024*1024);
4825
4826         // allocate a new buffer if the size is different (purge old one later)
4827         // or if we were told we must grow the buffer
4828         if (!mem || mem->size != size || mustgrow)
4829         {
4830                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4831                 mem->size = size;
4832                 mem->current = 0;
4833                 if (type == R_BUFFERDATA_VERTEX)
4834                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4835                 else if (type == R_BUFFERDATA_INDEX16)
4836                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4837                 else if (type == R_BUFFERDATA_INDEX32)
4838                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4839                 else if (type == R_BUFFERDATA_UNIFORM)
4840                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4841                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4842                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4843         }
4844 }
4845
4846 void R_BufferData_NewFrame(void)
4847 {
4848         int type;
4849         r_bufferdata_buffer_t **p, *mem;
4850         // cycle to the next frame's buffers
4851         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4852         // if we ran out of space on the last time we used these buffers, free the old memory now
4853         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4854         {
4855                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4856                 {
4857                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4858                         // free all but the head buffer, this is how we recycle obsolete
4859                         // buffers after they are no longer in use
4860                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4861                         while (*p)
4862                         {
4863                                 mem = *p;
4864                                 *p = (*p)->purge;
4865                                 if (mem->buffer)
4866                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4867                                 Mem_Free(mem);
4868                         }
4869                         // reset the current offset
4870                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4871                 }
4872         }
4873 }
4874
4875 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4876 {
4877         r_bufferdata_buffer_t *mem;
4878         int offset = 0;
4879         int padsize;
4880
4881         *returnbufferoffset = 0;
4882
4883         // align size to a byte boundary appropriate for the buffer type, this
4884         // makes all allocations have aligned start offsets
4885         if (type == R_BUFFERDATA_UNIFORM)
4886                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4887         else
4888                 padsize = (datasize + 15) & ~15;
4889
4890         // if we ran out of space in this buffer we must allocate a new one
4891         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)
4892                 R_BufferData_Resize(type, true, padsize);
4893
4894         // if the resize did not give us enough memory, fail
4895         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)
4896                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4897
4898         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4899         offset = (int)mem->current;
4900         mem->current += padsize;
4901
4902         // upload the data to the buffer at the chosen offset
4903         if (offset == 0)
4904                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4905         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4906
4907         // count the usage for stats
4908         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4909         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4910
4911         // return the buffer offset
4912         *returnbufferoffset = offset;
4913
4914         return mem->buffer;
4915 }
4916
4917 //==================================================================================
4918
4919 // LordHavoc: animcache originally written by Echon, rewritten since then
4920
4921 /**
4922  * Animation cache prevents re-generating mesh data for an animated model
4923  * multiple times in one frame for lighting, shadowing, reflections, etc.
4924  */
4925
4926 void R_AnimCache_Free(void)
4927 {
4928 }
4929
4930 void R_AnimCache_ClearCache(void)
4931 {
4932         int i;
4933         entity_render_t *ent;
4934
4935         for (i = 0;i < r_refdef.scene.numentities;i++)
4936         {
4937                 ent = r_refdef.scene.entities[i];
4938                 ent->animcache_vertex3f = NULL;
4939                 ent->animcache_vertex3f_vertexbuffer = NULL;
4940                 ent->animcache_vertex3f_bufferoffset = 0;
4941                 ent->animcache_normal3f = NULL;
4942                 ent->animcache_normal3f_vertexbuffer = NULL;
4943                 ent->animcache_normal3f_bufferoffset = 0;
4944                 ent->animcache_svector3f = NULL;
4945                 ent->animcache_svector3f_vertexbuffer = NULL;
4946                 ent->animcache_svector3f_bufferoffset = 0;
4947                 ent->animcache_tvector3f = NULL;
4948                 ent->animcache_tvector3f_vertexbuffer = NULL;
4949                 ent->animcache_tvector3f_bufferoffset = 0;
4950                 ent->animcache_vertexmesh = NULL;
4951                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4952                 ent->animcache_vertexmesh_bufferoffset = 0;
4953                 ent->animcache_skeletaltransform3x4 = NULL;
4954                 ent->animcache_skeletaltransform3x4buffer = NULL;
4955                 ent->animcache_skeletaltransform3x4offset = 0;
4956                 ent->animcache_skeletaltransform3x4size = 0;
4957         }
4958 }
4959
4960 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4961 {
4962         int i;
4963
4964         // check if we need the meshbuffers
4965         if (!vid.useinterleavedarrays)
4966                 return;
4967
4968         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4969                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4970         // TODO: upload vertexbuffer?
4971         if (ent->animcache_vertexmesh)
4972         {
4973                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4974                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4975                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4976                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4977                 for (i = 0;i < numvertices;i++)
4978                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4979                 if (ent->animcache_svector3f)
4980                         for (i = 0;i < numvertices;i++)
4981                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4982                 if (ent->animcache_tvector3f)
4983                         for (i = 0;i < numvertices;i++)
4984                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4985                 if (ent->animcache_normal3f)
4986                         for (i = 0;i < numvertices;i++)
4987                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4988         }
4989 }
4990
4991 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4992 {
4993         dp_model_t *model = ent->model;
4994         int numvertices;
4995
4996         // see if this ent is worth caching
4997         if (!model || !model->Draw || !model->AnimateVertices)
4998                 return false;
4999         // nothing to cache if it contains no animations and has no skeleton
5000         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5001                 return false;
5002         // see if it is already cached for gpuskeletal
5003         if (ent->animcache_skeletaltransform3x4)
5004                 return false;
5005         // see if it is already cached as a mesh
5006         if (ent->animcache_vertex3f)
5007         {
5008                 // check if we need to add normals or tangents
5009                 if (ent->animcache_normal3f)
5010                         wantnormals = false;
5011                 if (ent->animcache_svector3f)
5012                         wanttangents = false;
5013                 if (!wantnormals && !wanttangents)
5014                         return false;
5015         }
5016
5017         // check which kind of cache we need to generate
5018         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5019         {
5020                 // cache the skeleton so the vertex shader can use it
5021                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5022                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5023                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5024                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5025                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5026                 // note: this can fail if the buffer is at the grow limit
5027                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5028                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5029         }
5030         else if (ent->animcache_vertex3f)
5031         {
5032                 // mesh was already cached but we may need to add normals/tangents
5033                 // (this only happens with multiple views, reflections, cameras, etc)
5034                 if (wantnormals || wanttangents)
5035                 {
5036                         numvertices = model->surfmesh.num_vertices;
5037                         if (wantnormals)
5038                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5039                         if (wanttangents)
5040                         {
5041                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5042                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5043                         }
5044                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5045                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5046                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5047                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5048                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5049                 }
5050         }
5051         else
5052         {
5053                 // generate mesh cache
5054                 numvertices = model->surfmesh.num_vertices;
5055                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5056                 if (wantnormals)
5057                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5058                 if (wanttangents)
5059                 {
5060                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5061                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5062                 }
5063                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5064                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5065                 if (wantnormals || wanttangents)
5066                 {
5067                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5068                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5069                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5070                 }
5071                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5072                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5073                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5074         }
5075         return true;
5076 }
5077
5078 void R_AnimCache_CacheVisibleEntities(void)
5079 {
5080         int i;
5081         qboolean wantnormals = true;
5082         qboolean wanttangents = !r_showsurfaces.integer;
5083
5084         switch(vid.renderpath)
5085         {
5086         case RENDERPATH_GL20:
5087         case RENDERPATH_D3D9:
5088         case RENDERPATH_D3D10:
5089         case RENDERPATH_D3D11:
5090         case RENDERPATH_GLES2:
5091                 break;
5092         case RENDERPATH_GL11:
5093         case RENDERPATH_GL13:
5094         case RENDERPATH_GLES1:
5095                 wanttangents = false;
5096                 break;
5097         case RENDERPATH_SOFT:
5098                 break;
5099         }
5100
5101         if (r_shownormals.integer)
5102                 wanttangents = wantnormals = true;
5103
5104         // TODO: thread this
5105         // NOTE: R_PrepareRTLights() also caches entities
5106
5107         for (i = 0;i < r_refdef.scene.numentities;i++)
5108                 if (r_refdef.viewcache.entityvisible[i])
5109                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5110 }
5111
5112 //==================================================================================
5113
5114 extern cvar_t r_overheadsprites_pushback;
5115
5116 static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
5117 {
5118         vec3_t angles;
5119
5120         VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
5121         VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
5122
5123         // Use cl.viewangles and not r_refdef.view.forward here so it is the
5124         // same for all stereo views, and to better handle pitches outside
5125         // [-90, 90] (in_pitch_* cvars allow that).
5126         VectorCopy(cl.viewangles, angles);
5127         if (r_fullbright_directed_pitch_relative.integer) {
5128                 angles[PITCH] += r_fullbright_directed_pitch.value;
5129         } else {
5130                 angles[PITCH] = r_fullbright_directed_pitch.value;
5131         }
5132         AngleVectors(angles, worldspacenormal, NULL, NULL);
5133         VectorNegate(worldspacenormal, worldspacenormal);
5134 }
5135
5136 static void R_View_UpdateEntityLighting (void)
5137 {
5138         int i;
5139         entity_render_t *ent;
5140         vec3_t tempdiffusenormal, avg;
5141         vec_t f, fa, fd, fdd;
5142         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5143
5144         for (i = 0;i < r_refdef.scene.numentities;i++)
5145         {
5146                 ent = r_refdef.scene.entities[i];
5147
5148                 // skip unseen models
5149                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5150                         continue;
5151
5152                 // skip bsp models
5153                 if (ent->model && ent->model == cl.worldmodel)
5154                 {
5155                         // TODO: use modellight for r_ambient settings on world?
5156                         // The logic here currently matches RSurf_ActiveWorldEntity.
5157                         if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit))
5158                         {
5159                                 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5160                                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5161                                 if(VectorLength2(ent->modellight_lightdir) == 0)
5162                                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5163                                 VectorNormalize(ent->modellight_lightdir);
5164                         }
5165                         else
5166                         {
5167                                 VectorSet(ent->modellight_ambient, 0, 0, 0);
5168                                 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5169                                 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5170                         }
5171                         continue;
5172                 }
5173                 
5174                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5175                 {
5176                         // aleady updated by CSQC
5177                         // TODO: force modellight on BSP models in this case?
5178                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5179                 }
5180                 else
5181                 {
5182                         // fetch the lighting from the worldmodel data
5183                         VectorClear(ent->modellight_ambient);
5184                         VectorClear(ent->modellight_diffuse);
5185                         VectorClear(tempdiffusenormal);
5186                         if (ent->flags & RENDER_LIGHT)
5187                         {
5188                                 vec3_t org;
5189                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5190
5191                                 // complete lightning for lit sprites
5192                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5193                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5194                                 {
5195                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5196                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5197                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5198                                 }
5199                                 else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
5200                                 {
5201                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5202                                 }
5203                                 else if (r_fullbright_directed.integer)
5204                                 {
5205                                         R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5206                                 }
5207                                 else
5208                                 {
5209                                         VectorSet(ent->modellight_ambient, 1, 1, 1);
5210                                 }
5211
5212                                 if(ent->flags & RENDER_EQUALIZE)
5213                                 {
5214                                         // first fix up ambient lighting...
5215                                         if(r_equalize_entities_minambient.value > 0)
5216                                         {
5217                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5218                                                 if(fd > 0)
5219                                                 {
5220                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5221                                                         if(fa < r_equalize_entities_minambient.value * fd)
5222                                                         {
5223                                                                 // solve:
5224                                                                 //   fa'/fd' = minambient
5225                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5226                                                                 //   ...
5227                                                                 //   fa' = fd' * minambient
5228                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5229                                                                 //   ...
5230                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5231                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5232                                                                 //   ...
5233                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5234                                                                 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5235                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5236                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5237                                                         }
5238                                                 }
5239                                         }
5240
5241                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5242                                         {
5243                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5244                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5245                                                 f = fa + 0.25 * fd;
5246                                                 if(f > 0)
5247                                                 {
5248                                                         // adjust brightness and saturation to target
5249                                                         avg[0] = avg[1] = avg[2] = fa / f;
5250                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5251                                                         avg[0] = avg[1] = avg[2] = fd / f;
5252                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5253                                                 }
5254                                         }
5255                                 }
5256                         }
5257                         else
5258                         {
5259                                 // EF_FULLBRIGHT entity.
5260                                 if (r_fullbright_directed.integer)
5261                                 {
5262                                         R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5263                                 }
5264                                 else
5265                                 {
5266                                         VectorSet(ent->modellight_ambient, 1, 1, 1);
5267                                 }
5268                         }
5269                 }
5270
5271                 // move the light direction into modelspace coordinates for lighting code
5272                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5273                 if(VectorLength2(ent->modellight_lightdir) == 0)
5274                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5275                 VectorNormalize(ent->modellight_lightdir);
5276         }
5277 }
5278
5279 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5280 {
5281         int i;
5282         vec3_t eyemins, eyemaxs;
5283         vec3_t boxmins, boxmaxs;
5284         vec3_t start;
5285         vec3_t end;
5286         dp_model_t *model = r_refdef.scene.worldmodel;
5287         static vec3_t positions[] = {
5288                 { 0.5f, 0.5f, 0.5f },
5289                 { 0.0f, 0.0f, 0.0f },
5290                 { 0.0f, 0.0f, 1.0f },
5291                 { 0.0f, 1.0f, 0.0f },
5292                 { 0.0f, 1.0f, 1.0f },
5293                 { 1.0f, 0.0f, 0.0f },
5294                 { 1.0f, 0.0f, 1.0f },
5295                 { 1.0f, 1.0f, 0.0f },
5296                 { 1.0f, 1.0f, 1.0f },
5297         };
5298
5299         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5300         if (numsamples < 0)
5301                 return true;
5302
5303         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5304         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5305                 return true;
5306
5307         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5308                 return true;
5309
5310         // expand the eye box a little
5311         eyemins[0] = eye[0] - eyejitter;
5312         eyemaxs[0] = eye[0] + eyejitter;
5313         eyemins[1] = eye[1] - eyejitter;
5314         eyemaxs[1] = eye[1] + eyejitter;
5315         eyemins[2] = eye[2] - eyejitter;
5316         eyemaxs[2] = eye[2] + eyejitter;
5317         // expand the box a little
5318         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5319         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5320         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5321         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5322         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5323         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5324
5325         // return true if eye overlaps enlarged box
5326         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5327                 return true;
5328
5329         // try specific positions in the box first - note that these can be cached
5330         if (r_cullentities_trace_entityocclusion.integer)
5331         {
5332                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5333                 {
5334                         VectorCopy(eye, start);
5335                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5336                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5337                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5338                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5339                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5340                         // not picky - if the trace ended anywhere in the box we're good
5341                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5342                                 return true;
5343                 }
5344         }
5345         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5346                 return true;
5347
5348         // try various random positions
5349         for (i = 0; i < numsamples; i++)
5350         {
5351                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5352                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5353                 if (r_cullentities_trace_entityocclusion.integer)
5354                 {
5355                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5356                         // not picky - if the trace ended anywhere in the box we're good
5357                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5358                                 return true;
5359                 }
5360                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5361                         return true;
5362         }
5363
5364         return false;
5365 }
5366
5367
5368 static void R_View_UpdateEntityVisible (void)
5369 {
5370         int i;
5371         int renderimask;
5372         int samples;
5373         entity_render_t *ent;
5374
5375         if (r_refdef.envmap || r_fb.water.hideplayer)
5376                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5377         else if (chase_active.integer || r_fb.water.renderingscene)
5378                 renderimask = RENDER_VIEWMODEL;
5379         else
5380                 renderimask = RENDER_EXTERIORMODEL;
5381         if (!r_drawviewmodel.integer)
5382                 renderimask |= RENDER_VIEWMODEL;
5383         if (!r_drawexteriormodel.integer)
5384                 renderimask |= RENDER_EXTERIORMODEL;
5385         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5386         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5387         {
5388                 // worldmodel can check visibility
5389                 for (i = 0;i < r_refdef.scene.numentities;i++)
5390                 {
5391                         ent = r_refdef.scene.entities[i];
5392                         if (!(ent->flags & renderimask))
5393                         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)))
5394                         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))
5395                                 r_refdef.viewcache.entityvisible[i] = true;
5396                 }
5397         }
5398         else
5399         {
5400                 // no worldmodel or it can't check visibility
5401                 for (i = 0;i < r_refdef.scene.numentities;i++)
5402                 {
5403                         ent = r_refdef.scene.entities[i];
5404                         if (!(ent->flags & renderimask))
5405                         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)))
5406                                 r_refdef.viewcache.entityvisible[i] = true;
5407                 }
5408         }
5409         if (r_cullentities_trace.integer)
5410         {
5411                 for (i = 0;i < r_refdef.scene.numentities;i++)
5412                 {
5413                         if (!r_refdef.viewcache.entityvisible[i])
5414                                 continue;
5415                         ent = r_refdef.scene.entities[i];
5416                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5417                         {
5418                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5419                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5420                                         ent->last_trace_visibility = realtime;
5421                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5422                                         r_refdef.viewcache.entityvisible[i] = 0;
5423                         }
5424                 }
5425         }
5426 }
5427
5428 /// only used if skyrendermasked, and normally returns false
5429 static int R_DrawBrushModelsSky (void)
5430 {
5431         int i, sky;
5432         entity_render_t *ent;
5433
5434         sky = false;
5435         for (i = 0;i < r_refdef.scene.numentities;i++)
5436         {
5437                 if (!r_refdef.viewcache.entityvisible[i])
5438                         continue;
5439                 ent = r_refdef.scene.entities[i];
5440                 if (!ent->model || !ent->model->DrawSky)
5441                         continue;
5442                 ent->model->DrawSky(ent);
5443                 sky = true;
5444         }
5445         return sky;
5446 }
5447
5448 static void R_DrawNoModel(entity_render_t *ent);
5449 static void R_DrawModels(void)
5450 {
5451         int i;
5452         entity_render_t *ent;
5453
5454         for (i = 0;i < r_refdef.scene.numentities;i++)
5455         {
5456                 if (!r_refdef.viewcache.entityvisible[i])
5457                         continue;
5458                 ent = r_refdef.scene.entities[i];
5459                 r_refdef.stats[r_stat_entities]++;
5460                 /*
5461                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5462                 {
5463                         vec3_t f, l, u, o;
5464                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5465                         Con_Printf("R_DrawModels\n");
5466                         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]);
5467                         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);
5468                         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);
5469                 }
5470                 */
5471                 if (ent->model && ent->model->Draw != NULL)
5472                         ent->model->Draw(ent);
5473                 else
5474                         R_DrawNoModel(ent);
5475         }
5476 }
5477
5478 static void R_DrawModelsDepth(void)
5479 {
5480         int i;
5481         entity_render_t *ent;
5482
5483         for (i = 0;i < r_refdef.scene.numentities;i++)
5484         {
5485                 if (!r_refdef.viewcache.entityvisible[i])
5486                         continue;
5487                 ent = r_refdef.scene.entities[i];
5488                 if (ent->model && ent->model->DrawDepth != NULL)
5489                         ent->model->DrawDepth(ent);
5490         }
5491 }
5492
5493 static void R_DrawModelsDebug(void)
5494 {
5495         int i;
5496         entity_render_t *ent;
5497
5498         for (i = 0;i < r_refdef.scene.numentities;i++)
5499         {
5500                 if (!r_refdef.viewcache.entityvisible[i])
5501                         continue;
5502                 ent = r_refdef.scene.entities[i];
5503                 if (ent->model && ent->model->DrawDebug != NULL)
5504                         ent->model->DrawDebug(ent);
5505         }
5506 }
5507
5508 static void R_DrawModelsAddWaterPlanes(void)
5509 {
5510         int i;
5511         entity_render_t *ent;
5512
5513         for (i = 0;i < r_refdef.scene.numentities;i++)
5514         {
5515                 if (!r_refdef.viewcache.entityvisible[i])
5516                         continue;
5517                 ent = r_refdef.scene.entities[i];
5518                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5519                         ent->model->DrawAddWaterPlanes(ent);
5520         }
5521 }
5522
5523 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}};
5524
5525 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5526 {
5527         if (r_hdr_irisadaptation.integer)
5528         {
5529                 vec3_t p;
5530                 vec3_t ambient;
5531                 vec3_t diffuse;
5532                 vec3_t diffusenormal;
5533                 vec3_t forward;
5534                 vec_t brightness = 0.0f;
5535                 vec_t goal;
5536                 vec_t current;
5537                 vec_t d;
5538                 int c;
5539                 VectorCopy(r_refdef.view.forward, forward);
5540                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5541                 {
5542                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5543                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5544                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5545                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5546                         d = DotProduct(forward, diffusenormal);
5547                         brightness += VectorLength(ambient);
5548                         if (d > 0)
5549                                 brightness += d * VectorLength(diffuse);
5550                 }
5551                 brightness *= 1.0f / c;
5552                 brightness += 0.00001f; // make sure it's never zero
5553                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5554                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5555                 current = r_hdr_irisadaptation_value.value;
5556                 if (current < goal)
5557                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5558                 else if (current > goal)
5559                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5560                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5561                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5562         }
5563         else if (r_hdr_irisadaptation_value.value != 1.0f)
5564                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5565 }
5566
5567 static void R_View_SetFrustum(const int *scissor)
5568 {
5569         int i;
5570         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5571         vec3_t forward, left, up, origin, v;
5572
5573         if(scissor)
5574         {
5575                 // flipped x coordinates (because x points left here)
5576                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5577                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5578
5579                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5580                 switch(vid.renderpath)
5581                 {
5582                         case RENDERPATH_D3D9:
5583                         case RENDERPATH_D3D10:
5584                         case RENDERPATH_D3D11:
5585                                 // non-flipped y coordinates
5586                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5587                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5588                                 break;
5589                         case RENDERPATH_SOFT:
5590                         case RENDERPATH_GL11:
5591                         case RENDERPATH_GL13:
5592                         case RENDERPATH_GL20:
5593                         case RENDERPATH_GLES1:
5594                         case RENDERPATH_GLES2:
5595                                 // non-flipped y coordinates
5596                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5597                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5598                                 break;
5599                 }
5600         }
5601
5602         // we can't trust r_refdef.view.forward and friends in reflected scenes
5603         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5604
5605 #if 0
5606         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5607         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5608         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5609         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5610         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5611         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5612         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5613         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5614         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5615         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5616         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5617         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5618 #endif
5619
5620 #if 0
5621         zNear = r_refdef.nearclip;
5622         nudge = 1.0 - 1.0 / (1<<23);
5623         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5624         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5625         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5626         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5627         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5628         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5629         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5630         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5631 #endif
5632
5633
5634
5635 #if 0
5636         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5637         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5638         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5639         r_refdef.view.frustum[0].dist = m[15] - m[12];
5640
5641         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5642         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5643         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5644         r_refdef.view.frustum[1].dist = m[15] + m[12];
5645
5646         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5647         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5648         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5649         r_refdef.view.frustum[2].dist = m[15] - m[13];
5650
5651         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5652         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5653         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5654         r_refdef.view.frustum[3].dist = m[15] + m[13];
5655
5656         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5657         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5658         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5659         r_refdef.view.frustum[4].dist = m[15] - m[14];
5660
5661         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5662         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5663         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5664         r_refdef.view.frustum[5].dist = m[15] + m[14];
5665 #endif
5666
5667         if (r_refdef.view.useperspective)
5668         {
5669                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5670                 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]);
5671                 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]);
5672                 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]);
5673                 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]);
5674
5675                 // then the normals from the corners relative to origin
5676                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5677                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5678                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5679                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5680
5681                 // in a NORMAL view, forward cross left == up
5682                 // in a REFLECTED view, forward cross left == down
5683                 // so our cross products above need to be adjusted for a left handed coordinate system
5684                 CrossProduct(forward, left, v);
5685                 if(DotProduct(v, up) < 0)
5686                 {
5687                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5688                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5689                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5690                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5691                 }
5692
5693                 // Leaving those out was a mistake, those were in the old code, and they
5694                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5695                 // I couldn't reproduce it after adding those normalizations. --blub
5696                 VectorNormalize(r_refdef.view.frustum[0].normal);
5697                 VectorNormalize(r_refdef.view.frustum[1].normal);
5698                 VectorNormalize(r_refdef.view.frustum[2].normal);
5699                 VectorNormalize(r_refdef.view.frustum[3].normal);
5700
5701                 // make the corners absolute
5702                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5703                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5704                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5705                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5706
5707                 // one more normal
5708                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5709
5710                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5711                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5712                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5713                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5714                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5715         }
5716         else
5717         {
5718                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5719                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5720                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5721                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5722                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5723                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5724                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5725                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5726                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5727                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5728         }
5729         r_refdef.view.numfrustumplanes = 5;
5730
5731         if (r_refdef.view.useclipplane)
5732         {
5733                 r_refdef.view.numfrustumplanes = 6;
5734                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5735         }
5736
5737         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5738                 PlaneClassify(r_refdef.view.frustum + i);
5739
5740         // LordHavoc: note to all quake engine coders, Quake had a special case
5741         // for 90 degrees which assumed a square view (wrong), so I removed it,
5742         // Quake2 has it disabled as well.
5743
5744         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5745         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5746         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5747         //PlaneClassify(&frustum[0]);
5748
5749         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5750         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5751         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5752         //PlaneClassify(&frustum[1]);
5753
5754         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5755         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5756         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5757         //PlaneClassify(&frustum[2]);
5758
5759         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5760         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5761         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5762         //PlaneClassify(&frustum[3]);
5763
5764         // nearclip plane
5765         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5766         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5767         //PlaneClassify(&frustum[4]);
5768 }
5769
5770 static void R_View_UpdateWithScissor(const int *myscissor)
5771 {
5772         R_Main_ResizeViewCache();
5773         R_View_SetFrustum(myscissor);
5774         R_View_WorldVisibility(r_refdef.view.useclipplane);
5775         R_View_UpdateEntityVisible();
5776         R_View_UpdateEntityLighting();
5777 }
5778
5779 static void R_View_Update(void)
5780 {
5781         R_Main_ResizeViewCache();
5782         R_View_SetFrustum(NULL);
5783         R_View_WorldVisibility(r_refdef.view.useclipplane);
5784         R_View_UpdateEntityVisible();
5785         R_View_UpdateEntityLighting();
5786 }
5787
5788 float viewscalefpsadjusted = 1.0f;
5789
5790 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5791 {
5792         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5793         scale = bound(0.03125f, scale, 1.0f);
5794         *outwidth = (int)ceil(width * scale);
5795         *outheight = (int)ceil(height * scale);
5796 }
5797
5798 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5799 {
5800         const float *customclipplane = NULL;
5801         float plane[4];
5802         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5803         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5804         {
5805                 // LordHavoc: couldn't figure out how to make this approach the
5806                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5807                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5808                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5809                         dist = r_refdef.view.clipplane.dist;
5810                 plane[0] = r_refdef.view.clipplane.normal[0];
5811                 plane[1] = r_refdef.view.clipplane.normal[1];
5812                 plane[2] = r_refdef.view.clipplane.normal[2];
5813                 plane[3] = -dist;
5814                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5815         }
5816
5817         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5818         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5819
5820         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5821         if (!r_refdef.view.useperspective)
5822                 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);
5823         else if (vid.stencil && r_useinfinitefarclip.integer)
5824                 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);
5825         else
5826                 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);
5827         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5828         R_SetViewport(&r_refdef.view.viewport);
5829         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5830         {
5831                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5832                 float screenplane[4];
5833                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5834                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5835                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5836                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5837                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5838         }
5839 }
5840
5841 void R_EntityMatrix(const matrix4x4_t *matrix)
5842 {
5843         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5844         {
5845                 gl_modelmatrixchanged = false;
5846                 gl_modelmatrix = *matrix;
5847                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5848                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5849                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5850                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5851                 CHECKGLERROR
5852                 switch(vid.renderpath)
5853                 {
5854                 case RENDERPATH_D3D9:
5855 #ifdef SUPPORTD3D
5856                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5857                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5858 #endif
5859                         break;
5860                 case RENDERPATH_D3D10:
5861                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5862                         break;
5863                 case RENDERPATH_D3D11:
5864                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5865                         break;
5866                 case RENDERPATH_GL11:
5867                 case RENDERPATH_GL13:
5868                 case RENDERPATH_GLES1:
5869 #ifndef USE_GLES2
5870                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5871 #endif
5872                         break;
5873                 case RENDERPATH_SOFT:
5874                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5875                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5876                         break;
5877                 case RENDERPATH_GL20:
5878                 case RENDERPATH_GLES2:
5879                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5880                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5881                         break;
5882                 }
5883         }
5884 }
5885
5886 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5887 {
5888         r_viewport_t viewport;
5889
5890         CHECKGLERROR
5891
5892         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5893         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);
5894         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5895         R_SetViewport(&viewport);
5896         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5897         GL_Color(1, 1, 1, 1);
5898         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5899         GL_BlendFunc(GL_ONE, GL_ZERO);
5900         GL_ScissorTest(false);
5901         GL_DepthMask(false);
5902         GL_DepthRange(0, 1);
5903         GL_DepthTest(false);
5904         GL_DepthFunc(GL_LEQUAL);
5905         R_EntityMatrix(&identitymatrix);
5906         R_Mesh_ResetTextureState();
5907         GL_PolygonOffset(0, 0);
5908         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5909         switch(vid.renderpath)
5910         {
5911         case RENDERPATH_GL11:
5912         case RENDERPATH_GL13:
5913         case RENDERPATH_GL20:
5914         case RENDERPATH_GLES1:
5915         case RENDERPATH_GLES2:
5916                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5917                 break;
5918         case RENDERPATH_D3D9:
5919         case RENDERPATH_D3D10:
5920         case RENDERPATH_D3D11:
5921         case RENDERPATH_SOFT:
5922                 break;
5923         }
5924         GL_CullFace(GL_NONE);
5925
5926         CHECKGLERROR
5927 }
5928
5929 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5930 {
5931         DrawQ_Finish();
5932
5933         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5934 }
5935
5936 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5937 {
5938         DrawQ_Finish();
5939
5940         R_SetupView(true, fbo, depthtexture, colortexture);
5941         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5942         GL_Color(1, 1, 1, 1);
5943         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5944         GL_BlendFunc(GL_ONE, GL_ZERO);
5945         GL_ScissorTest(true);
5946         GL_DepthMask(true);
5947         GL_DepthRange(0, 1);
5948         GL_DepthTest(true);
5949         GL_DepthFunc(GL_LEQUAL);
5950         R_EntityMatrix(&identitymatrix);
5951         R_Mesh_ResetTextureState();
5952         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5953         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5954         switch(vid.renderpath)
5955         {
5956         case RENDERPATH_GL11:
5957         case RENDERPATH_GL13:
5958         case RENDERPATH_GL20:
5959         case RENDERPATH_GLES1:
5960         case RENDERPATH_GLES2:
5961                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5962                 break;
5963         case RENDERPATH_D3D9:
5964         case RENDERPATH_D3D10:
5965         case RENDERPATH_D3D11:
5966         case RENDERPATH_SOFT:
5967                 break;
5968         }
5969         GL_CullFace(r_refdef.view.cullface_back);
5970 }
5971
5972 /*
5973 ================
5974 R_RenderView_UpdateViewVectors
5975 ================
5976 */
5977 void R_RenderView_UpdateViewVectors(void)
5978 {
5979         // break apart the view matrix into vectors for various purposes
5980         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5981         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5982         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5983         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5984         // make an inverted copy of the view matrix for tracking sprites
5985         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5986 }
5987
5988 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5989 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5990
5991 static void R_Water_StartFrame(void)
5992 {
5993         int i;
5994         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5995         r_waterstate_waterplane_t *p;
5996         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;
5997
5998         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5999                 return;
6000
6001         switch(vid.renderpath)
6002         {
6003         case RENDERPATH_GL20:
6004         case RENDERPATH_D3D9:
6005         case RENDERPATH_D3D10:
6006         case RENDERPATH_D3D11:
6007         case RENDERPATH_SOFT:
6008         case RENDERPATH_GLES2:
6009                 break;
6010         case RENDERPATH_GL11:
6011         case RENDERPATH_GL13:
6012         case RENDERPATH_GLES1:
6013                 return;
6014         }
6015
6016         // set waterwidth and waterheight to the water resolution that will be
6017         // used (often less than the screen resolution for faster rendering)
6018         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
6019
6020         // calculate desired texture sizes
6021         // can't use water if the card does not support the texture size
6022         if (!r_water.integer || r_showsurfaces.integer)
6023                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
6024         else if (vid.support.arb_texture_non_power_of_two)
6025         {
6026                 texturewidth = waterwidth;
6027                 textureheight = waterheight;
6028                 camerawidth = waterwidth;
6029                 cameraheight = waterheight;
6030         }
6031         else
6032         {
6033                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
6034                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
6035                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
6036                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
6037         }
6038
6039         // allocate textures as needed
6040         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))
6041         {
6042                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6043                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
6044                 {
6045                         if (p->texture_refraction)
6046                                 R_FreeTexture(p->texture_refraction);
6047                         p->texture_refraction = NULL;
6048                         if (p->fbo_refraction)
6049                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
6050                         p->fbo_refraction = 0;
6051                         if (p->texture_reflection)
6052                                 R_FreeTexture(p->texture_reflection);
6053                         p->texture_reflection = NULL;
6054                         if (p->fbo_reflection)
6055                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6056                         p->fbo_reflection = 0;
6057                         if (p->texture_camera)
6058                                 R_FreeTexture(p->texture_camera);
6059                         p->texture_camera = NULL;
6060                         if (p->fbo_camera)
6061                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6062                         p->fbo_camera = 0;
6063                 }
6064                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6065                 r_fb.water.texturewidth = texturewidth;
6066                 r_fb.water.textureheight = textureheight;
6067                 r_fb.water.camerawidth = camerawidth;
6068                 r_fb.water.cameraheight = cameraheight;
6069         }
6070
6071         if (r_fb.water.texturewidth)
6072         {
6073                 int scaledwidth, scaledheight;
6074
6075                 r_fb.water.enabled = true;
6076
6077                 // water resolution is usually reduced
6078                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6079                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6080                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6081
6082                 // set up variables that will be used in shader setup
6083                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6084                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6085                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6086                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6087         }
6088
6089         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6090         r_fb.water.numwaterplanes = 0;
6091 }
6092
6093 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6094 {
6095         int planeindex, bestplaneindex, vertexindex;
6096         vec3_t mins, maxs, normal, center, v, n;
6097         vec_t planescore, bestplanescore;
6098         mplane_t plane;
6099         r_waterstate_waterplane_t *p;
6100         texture_t *t = R_GetCurrentTexture(surface->texture);
6101
6102         rsurface.texture = t;
6103         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6104         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6105         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6106                 return;
6107         // average the vertex normals, find the surface bounds (after deformvertexes)
6108         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6109         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6110         VectorCopy(n, normal);
6111         VectorCopy(v, mins);
6112         VectorCopy(v, maxs);
6113         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6114         {
6115                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6116                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6117                 VectorAdd(normal, n, normal);
6118                 mins[0] = min(mins[0], v[0]);
6119                 mins[1] = min(mins[1], v[1]);
6120                 mins[2] = min(mins[2], v[2]);
6121                 maxs[0] = max(maxs[0], v[0]);
6122                 maxs[1] = max(maxs[1], v[1]);
6123                 maxs[2] = max(maxs[2], v[2]);
6124         }
6125         VectorNormalize(normal);
6126         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6127
6128         VectorCopy(normal, plane.normal);
6129         VectorNormalize(plane.normal);
6130         plane.dist = DotProduct(center, plane.normal);
6131         PlaneClassify(&plane);
6132         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6133         {
6134                 // skip backfaces (except if nocullface is set)
6135 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6136 //                      return;
6137                 VectorNegate(plane.normal, plane.normal);
6138                 plane.dist *= -1;
6139                 PlaneClassify(&plane);
6140         }
6141
6142
6143         // find a matching plane if there is one
6144         bestplaneindex = -1;
6145         bestplanescore = 1048576.0f;
6146         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6147         {
6148                 if(p->camera_entity == t->camera_entity)
6149                 {
6150                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6151                         if (bestplaneindex < 0 || bestplanescore > planescore)
6152                         {
6153                                 bestplaneindex = planeindex;
6154                                 bestplanescore = planescore;
6155                         }
6156                 }
6157         }
6158         planeindex = bestplaneindex;
6159
6160         // if this surface does not fit any known plane rendered this frame, add one
6161         if (planeindex < 0 || bestplanescore > 0.001f)
6162         {
6163                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6164                 {
6165                         // store the new plane
6166                         planeindex = r_fb.water.numwaterplanes++;
6167                         p = r_fb.water.waterplanes + planeindex;
6168                         p->plane = plane;
6169                         // clear materialflags and pvs
6170                         p->materialflags = 0;
6171                         p->pvsvalid = false;
6172                         p->camera_entity = t->camera_entity;
6173                         VectorCopy(mins, p->mins);
6174                         VectorCopy(maxs, p->maxs);
6175                 }
6176                 else
6177                 {
6178                         // We're totally screwed.
6179                         return;
6180                 }
6181         }
6182         else
6183         {
6184                 // merge mins/maxs when we're adding this surface to the plane
6185                 p = r_fb.water.waterplanes + planeindex;
6186                 p->mins[0] = min(p->mins[0], mins[0]);
6187                 p->mins[1] = min(p->mins[1], mins[1]);
6188                 p->mins[2] = min(p->mins[2], mins[2]);
6189                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6190                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6191                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6192         }
6193         // merge this surface's materialflags into the waterplane
6194         p->materialflags |= t->currentmaterialflags;
6195         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6196         {
6197                 // merge this surface's PVS into the waterplane
6198                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6199                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6200                 {
6201                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6202                         p->pvsvalid = true;
6203                 }
6204         }
6205 }
6206
6207 extern cvar_t r_drawparticles;
6208 extern cvar_t r_drawdecals;
6209
6210 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6211 {
6212         int myscissor[4];
6213         r_refdef_view_t originalview;
6214         r_refdef_view_t myview;
6215         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;
6216         r_waterstate_waterplane_t *p;
6217         vec3_t visorigin;
6218         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;
6219         char vabuf[1024];
6220
6221         originalview = r_refdef.view;
6222
6223         // lowquality hack, temporarily shut down some cvars and restore afterwards
6224         qualityreduction = r_water_lowquality.integer;
6225         if (qualityreduction > 0)
6226         {
6227                 if (qualityreduction >= 1)
6228                 {
6229                         old_r_shadows = r_shadows.integer;
6230                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6231                         old_r_dlight = r_shadow_realtime_dlight.integer;
6232                         Cvar_SetValueQuick(&r_shadows, 0);
6233                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6234                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6235                 }
6236                 if (qualityreduction >= 2)
6237                 {
6238                         old_r_dynamic = r_dynamic.integer;
6239                         old_r_particles = r_drawparticles.integer;
6240                         old_r_decals = r_drawdecals.integer;
6241                         Cvar_SetValueQuick(&r_dynamic, 0);
6242                         Cvar_SetValueQuick(&r_drawparticles, 0);
6243                         Cvar_SetValueQuick(&r_drawdecals, 0);
6244                 }
6245         }
6246
6247         // make sure enough textures are allocated
6248         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6249         {
6250                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6251                         continue;
6252                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6253                 {
6254                         if (!p->texture_refraction)
6255                                 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);
6256                         if (!p->texture_refraction)
6257                                 goto error;
6258                         if (usewaterfbo)
6259                         {
6260                                 if (r_fb.water.depthtexture == NULL)
6261                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6262                                 if (p->fbo_refraction == 0)
6263                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6264                         }
6265                 }
6266                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6267                 {
6268                         if (!p->texture_camera)
6269                                 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);
6270                         if (!p->texture_camera)
6271                                 goto error;
6272                         if (usewaterfbo)
6273                         {
6274                                 if (r_fb.water.depthtexture == NULL)
6275                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6276                                 if (p->fbo_camera == 0)
6277                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6278                         }
6279                 }
6280
6281                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6282                 {
6283                         if (!p->texture_reflection)
6284                                 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);
6285                         if (!p->texture_reflection)
6286                                 goto error;
6287                         if (usewaterfbo)
6288                         {
6289                                 if (r_fb.water.depthtexture == NULL)
6290                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6291                                 if (p->fbo_reflection == 0)
6292                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6293                         }
6294                 }
6295         }
6296
6297         // render views
6298         r_refdef.view = originalview;
6299         r_refdef.view.showdebug = false;
6300         r_refdef.view.width = r_fb.water.waterwidth;
6301         r_refdef.view.height = r_fb.water.waterheight;
6302         r_refdef.view.useclipplane = true;
6303         myview = r_refdef.view;
6304         r_fb.water.renderingscene = true;
6305         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6306         {
6307                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6308                         continue;
6309                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6310                 {
6311                         r_refdef.view = myview;
6312                         if(r_water_scissormode.integer)
6313                         {
6314                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6315                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6316                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6317                         }
6318
6319                         // render reflected scene and copy into texture
6320                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6321                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6322                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6323                         r_refdef.view.clipplane = p->plane;
6324                         // reverse the cullface settings for this render
6325                         r_refdef.view.cullface_front = GL_FRONT;
6326                         r_refdef.view.cullface_back = GL_BACK;
6327                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6328                         {
6329                                 r_refdef.view.usecustompvs = true;
6330                                 if (p->pvsvalid)
6331                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6332                                 else
6333                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6334                         }
6335
6336                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6337                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6338                         R_ClearScreen(r_refdef.fogenabled);
6339                         if(r_water_scissormode.integer & 2)
6340                                 R_View_UpdateWithScissor(myscissor);
6341                         else
6342                                 R_View_Update();
6343                         R_AnimCache_CacheVisibleEntities();
6344                         if(r_water_scissormode.integer & 1)
6345                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6346                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6347
6348                         if (!p->fbo_reflection)
6349                                 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);
6350                         r_fb.water.hideplayer = false;
6351                 }
6352
6353                 // render the normal view scene and copy into texture
6354                 // (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)
6355                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6356                 {
6357                         r_refdef.view = myview;
6358                         if(r_water_scissormode.integer)
6359                         {
6360                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6361                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6362                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6363                         }
6364
6365                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6366
6367                         r_refdef.view.clipplane = p->plane;
6368                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6369                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6370
6371                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6372                         {
6373                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6374                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6375                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6376                                 R_RenderView_UpdateViewVectors();
6377                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6378                                 {
6379                                         r_refdef.view.usecustompvs = true;
6380                                         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);
6381                                 }
6382                         }
6383
6384                         PlaneClassify(&r_refdef.view.clipplane);
6385
6386                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6387                         R_ClearScreen(r_refdef.fogenabled);
6388                         if(r_water_scissormode.integer & 2)
6389                                 R_View_UpdateWithScissor(myscissor);
6390                         else
6391                                 R_View_Update();
6392                         R_AnimCache_CacheVisibleEntities();
6393                         if(r_water_scissormode.integer & 1)
6394                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6395                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6396
6397                         if (!p->fbo_refraction)
6398                                 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);
6399                         r_fb.water.hideplayer = false;
6400                 }
6401                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6402                 {
6403                         r_refdef.view = myview;
6404
6405                         r_refdef.view.clipplane = p->plane;
6406                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6407                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6408
6409                         r_refdef.view.width = r_fb.water.camerawidth;
6410                         r_refdef.view.height = r_fb.water.cameraheight;
6411                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6412                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6413                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6414                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6415
6416                         if(p->camera_entity)
6417                         {
6418                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6419                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6420                         }
6421
6422                         // note: all of the view is used for displaying... so
6423                         // there is no use in scissoring
6424
6425                         // reverse the cullface settings for this render
6426                         r_refdef.view.cullface_front = GL_FRONT;
6427                         r_refdef.view.cullface_back = GL_BACK;
6428                         // also reverse the view matrix
6429                         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
6430                         R_RenderView_UpdateViewVectors();
6431                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6432                         {
6433                                 r_refdef.view.usecustompvs = true;
6434                                 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);
6435                         }
6436                         
6437                         // camera needs no clipplane
6438                         r_refdef.view.useclipplane = false;
6439
6440                         PlaneClassify(&r_refdef.view.clipplane);
6441
6442                         r_fb.water.hideplayer = false;
6443
6444                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6445                         R_ClearScreen(r_refdef.fogenabled);
6446                         R_View_Update();
6447                         R_AnimCache_CacheVisibleEntities();
6448                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6449
6450                         if (!p->fbo_camera)
6451                                 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);
6452                         r_fb.water.hideplayer = false;
6453                 }
6454
6455         }
6456         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6457         r_fb.water.renderingscene = false;
6458         r_refdef.view = originalview;
6459         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6460         if (!r_fb.water.depthtexture)
6461                 R_ClearScreen(r_refdef.fogenabled);
6462         R_View_Update();
6463         R_AnimCache_CacheVisibleEntities();
6464         goto finish;
6465 error:
6466         r_refdef.view = originalview;
6467         r_fb.water.renderingscene = false;
6468         Cvar_SetValueQuick(&r_water, 0);
6469         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6470 finish:
6471         // lowquality hack, restore cvars
6472         if (qualityreduction > 0)
6473         {
6474                 if (qualityreduction >= 1)
6475                 {
6476                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6477                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6478                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6479                 }
6480                 if (qualityreduction >= 2)
6481                 {
6482                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6483                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6484                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6485                 }
6486         }
6487 }
6488
6489 static void R_Bloom_StartFrame(void)
6490 {
6491         int i;
6492         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6493         int viewwidth, viewheight;
6494         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6495         textype_t textype = TEXTYPE_COLORBUFFER;
6496
6497         switch (vid.renderpath)
6498         {
6499         case RENDERPATH_GL20:
6500                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6501                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6502                 {
6503                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6504                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6505                 }
6506                 break;
6507         case RENDERPATH_GL11:
6508         case RENDERPATH_GL13:
6509         case RENDERPATH_GLES1:
6510                 return; // don't bother
6511         case RENDERPATH_GLES2:
6512         case RENDERPATH_D3D9:
6513         case RENDERPATH_D3D10:
6514         case RENDERPATH_D3D11:
6515                 r_fb.usedepthtextures = false;
6516                 break;
6517         case RENDERPATH_SOFT:
6518                 r_fb.usedepthtextures = true;
6519                 break;
6520         }
6521
6522         if (r_viewscale_fpsscaling.integer)
6523         {
6524                 double actualframetime;
6525                 double targetframetime;
6526                 double adjust;
6527                 actualframetime = r_refdef.lastdrawscreentime;
6528                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6529                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6530                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6531                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6532                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6533                 viewscalefpsadjusted += adjust;
6534                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6535         }
6536         else
6537                 viewscalefpsadjusted = 1.0f;
6538
6539         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6540
6541         switch(vid.renderpath)
6542         {
6543         case RENDERPATH_GL20:
6544         case RENDERPATH_D3D9:
6545         case RENDERPATH_D3D10:
6546         case RENDERPATH_D3D11:
6547         case RENDERPATH_SOFT:
6548         case RENDERPATH_GLES2:
6549                 break;
6550         case RENDERPATH_GL11:
6551         case RENDERPATH_GL13:
6552         case RENDERPATH_GLES1:
6553                 return;
6554         }
6555
6556         // set bloomwidth and bloomheight to the bloom resolution that will be
6557         // used (often less than the screen resolution for faster rendering)
6558         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6559         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6560         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6561         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6562         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6563
6564         // calculate desired texture sizes
6565         if (vid.support.arb_texture_non_power_of_two)
6566         {
6567                 screentexturewidth = vid.width;
6568                 screentextureheight = vid.height;
6569                 bloomtexturewidth = r_fb.bloomwidth;
6570                 bloomtextureheight = r_fb.bloomheight;
6571         }
6572         else
6573         {
6574                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6575                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6576                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6577                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6578         }
6579
6580         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))
6581         {
6582                 Cvar_SetValueQuick(&r_bloom, 0);
6583                 Cvar_SetValueQuick(&r_motionblur, 0);
6584                 Cvar_SetValueQuick(&r_damageblur, 0);
6585         }
6586
6587         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6588          && !r_bloom.integer
6589          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6590          && !useviewfbo
6591          && r_viewscale.value == 1.0f
6592          && !r_viewscale_fpsscaling.integer)
6593                 screentexturewidth = screentextureheight = 0;
6594         if (!r_bloom.integer)
6595                 bloomtexturewidth = bloomtextureheight = 0;
6596
6597         // allocate textures as needed
6598         if (r_fb.screentexturewidth != screentexturewidth
6599          || r_fb.screentextureheight != screentextureheight
6600          || r_fb.bloomtexturewidth != bloomtexturewidth
6601          || r_fb.bloomtextureheight != bloomtextureheight
6602          || r_fb.textype != textype
6603          || useviewfbo != (r_fb.fbo != 0))
6604         {
6605                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6606                 {
6607                         if (r_fb.bloomtexture[i])
6608                                 R_FreeTexture(r_fb.bloomtexture[i]);
6609                         r_fb.bloomtexture[i] = NULL;
6610
6611                         if (r_fb.bloomfbo[i])
6612                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6613                         r_fb.bloomfbo[i] = 0;
6614                 }
6615
6616                 if (r_fb.fbo)
6617                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6618                 r_fb.fbo = 0;
6619
6620                 if (r_fb.colortexture)
6621                         R_FreeTexture(r_fb.colortexture);
6622                 r_fb.colortexture = NULL;
6623
6624                 if (r_fb.depthtexture)
6625                         R_FreeTexture(r_fb.depthtexture);
6626                 r_fb.depthtexture = NULL;
6627
6628                 if (r_fb.ghosttexture)
6629                         R_FreeTexture(r_fb.ghosttexture);
6630                 r_fb.ghosttexture = NULL;
6631
6632                 r_fb.screentexturewidth = screentexturewidth;
6633                 r_fb.screentextureheight = screentextureheight;
6634                 r_fb.bloomtexturewidth = bloomtexturewidth;
6635                 r_fb.bloomtextureheight = bloomtextureheight;
6636                 r_fb.textype = textype;
6637
6638                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6639                 {
6640                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6641                                 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);
6642                         r_fb.ghosttexture_valid = false;
6643                         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);
6644                         if (useviewfbo)
6645                         {
6646                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6647                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6648                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6649                         }
6650                 }
6651
6652                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6653                 {
6654                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6655                         {
6656                                 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);
6657                                 if (useviewfbo)
6658                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6659                         }
6660                 }
6661         }
6662
6663         // bloom texture is a different resolution
6664         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6665         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6666         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6667         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6668         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6669
6670         // set up a texcoord array for the full resolution screen image
6671         // (we have to keep this around to copy back during final render)
6672         r_fb.screentexcoord2f[0] = 0;
6673         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6674         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6675         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6676         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6677         r_fb.screentexcoord2f[5] = 0;
6678         r_fb.screentexcoord2f[6] = 0;
6679         r_fb.screentexcoord2f[7] = 0;
6680
6681         if(r_fb.fbo) 
6682         {
6683                 for (i = 1;i < 8;i += 2)
6684                 {
6685                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6686                 }
6687         }
6688
6689         // set up a texcoord array for the reduced resolution bloom image
6690         // (which will be additive blended over the screen image)
6691         r_fb.bloomtexcoord2f[0] = 0;
6692         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6693         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6694         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6695         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6696         r_fb.bloomtexcoord2f[5] = 0;
6697         r_fb.bloomtexcoord2f[6] = 0;
6698         r_fb.bloomtexcoord2f[7] = 0;
6699
6700         switch(vid.renderpath)
6701         {
6702         case RENDERPATH_GL11:
6703         case RENDERPATH_GL13:
6704         case RENDERPATH_GL20:
6705         case RENDERPATH_SOFT:
6706         case RENDERPATH_GLES1:
6707         case RENDERPATH_GLES2:
6708                 break;
6709         case RENDERPATH_D3D9:
6710         case RENDERPATH_D3D10:
6711         case RENDERPATH_D3D11:
6712                 for (i = 0;i < 4;i++)
6713                 {
6714                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6715                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6716                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6717                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6718                 }
6719                 break;
6720         }
6721
6722         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6723
6724         if (r_fb.fbo)
6725                 r_refdef.view.clear = true;
6726 }
6727
6728 static void R_Bloom_MakeTexture(void)
6729 {
6730         int x, range, dir;
6731         float xoffset, yoffset, r, brighten;
6732         rtexture_t *intex;
6733         float colorscale = r_bloom_colorscale.value;
6734
6735         r_refdef.stats[r_stat_bloom]++;
6736     
6737 #if 0
6738     // this copy is unnecessary since it happens in R_BlendView already
6739         if (!r_fb.fbo)
6740         {
6741                 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);
6742                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6743         }
6744 #endif
6745
6746         // scale down screen texture to the bloom texture size
6747         CHECKGLERROR
6748         r_fb.bloomindex = 0;
6749         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6750         R_SetViewport(&r_fb.bloomviewport);
6751         GL_CullFace(GL_NONE);
6752         GL_DepthTest(false);
6753         GL_BlendFunc(GL_ONE, GL_ZERO);
6754         GL_Color(colorscale, colorscale, colorscale, 1);
6755         // 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...
6756         switch(vid.renderpath)
6757         {
6758         case RENDERPATH_GL11:
6759         case RENDERPATH_GL13:
6760         case RENDERPATH_GL20:
6761         case RENDERPATH_GLES1:
6762         case RENDERPATH_GLES2:
6763         case RENDERPATH_SOFT:
6764                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6765                 break;
6766         case RENDERPATH_D3D9:
6767         case RENDERPATH_D3D10:
6768         case RENDERPATH_D3D11:
6769                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6770                 break;
6771         }
6772         // TODO: do boxfilter scale-down in shader?
6773         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6774         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6775         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6776
6777         // we now have a properly scaled bloom image
6778         if (!r_fb.bloomfbo[r_fb.bloomindex])
6779         {
6780                 // copy it into the bloom texture
6781                 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);
6782                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6783         }
6784
6785         // multiply bloom image by itself as many times as desired
6786         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6787         {
6788                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6789                 r_fb.bloomindex ^= 1;
6790                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6791                 x *= 2;
6792                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6793                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6794                 {
6795                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6796                         GL_Color(r,r,r,1); // apply fix factor
6797                 }
6798                 else
6799                 {
6800                         if(x <= 2)
6801                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6802                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6803                         GL_Color(1,1,1,1); // no fix factor supported here
6804                 }
6805                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6806                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6807                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6808                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6809
6810                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6811                 {
6812                         // copy the darkened image to a texture
6813                         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);
6814                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6815                 }
6816         }
6817
6818         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6819         brighten = r_bloom_brighten.value;
6820         brighten = sqrt(brighten);
6821         if(range >= 1)
6822                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6823
6824         for (dir = 0;dir < 2;dir++)
6825         {
6826                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6827                 r_fb.bloomindex ^= 1;
6828                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6829                 // blend on at multiple vertical offsets to achieve a vertical blur
6830                 // TODO: do offset blends using GLSL
6831                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6832                 GL_BlendFunc(GL_ONE, GL_ZERO);
6833                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6834                 for (x = -range;x <= range;x++)
6835                 {
6836                         if (!dir){xoffset = 0;yoffset = x;}
6837                         else {xoffset = x;yoffset = 0;}
6838                         xoffset /= (float)r_fb.bloomtexturewidth;
6839                         yoffset /= (float)r_fb.bloomtextureheight;
6840                         // compute a texcoord array with the specified x and y offset
6841                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6842                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6843                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6844                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6845                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6846                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6847                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6848                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6849                         // this r value looks like a 'dot' particle, fading sharply to
6850                         // black at the edges
6851                         // (probably not realistic but looks good enough)
6852                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6853                         //r = brighten/(range*2+1);
6854                         r = brighten / (range * 2 + 1);
6855                         if(range >= 1)
6856                                 r *= (1 - x*x/(float)(range*range));
6857                         GL_Color(r, r, r, 1);
6858                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6859                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6860                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6861                         GL_BlendFunc(GL_ONE, GL_ONE);
6862                 }
6863
6864                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6865                 {
6866                         // copy the vertically or horizontally blurred bloom view to a texture
6867                         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);
6868                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6869                 }
6870         }
6871 }
6872
6873 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6874 {
6875         dpuint64 permutation;
6876         float uservecs[4][4];
6877
6878         R_EntityMatrix(&identitymatrix);
6879
6880         switch (vid.renderpath)
6881         {
6882         case RENDERPATH_GL20:
6883         case RENDERPATH_D3D9:
6884         case RENDERPATH_D3D10:
6885         case RENDERPATH_D3D11:
6886         case RENDERPATH_SOFT:
6887         case RENDERPATH_GLES2:
6888                 permutation =
6889                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6890                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6891                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6892                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6893                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6894
6895                 if (r_fb.colortexture)
6896                 {
6897                         if (!r_fb.fbo)
6898                         {
6899                                 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);
6900                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6901                         }
6902
6903                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6904                         {
6905                                 // declare variables
6906                                 float blur_factor, blur_mouseaccel, blur_velocity;
6907                                 static float blur_average; 
6908                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6909
6910                                 // set a goal for the factoring
6911                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6912                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6913                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6914                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6915                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6916                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6917
6918                                 // from the goal, pick an averaged value between goal and last value
6919                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6920                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6921
6922                                 // enforce minimum amount of blur 
6923                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6924
6925                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6926
6927                                 // calculate values into a standard alpha
6928                                 cl.motionbluralpha = 1 - exp(-
6929                                                 (
6930                                                  (r_motionblur.value * blur_factor / 80)
6931                                                  +
6932                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6933                                                 )
6934                                                 /
6935                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6936                                           );
6937
6938                                 // randomization for the blur value to combat persistent ghosting
6939                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6940                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6941
6942                                 // apply the blur
6943                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6944                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6945                                 {
6946                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6947                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6948                                         switch(vid.renderpath)
6949                                         {
6950                                         case RENDERPATH_GL11:
6951                                         case RENDERPATH_GL13:
6952                                         case RENDERPATH_GL20:
6953                                         case RENDERPATH_GLES1:
6954                                         case RENDERPATH_GLES2:
6955                                         case RENDERPATH_SOFT:
6956                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6957                                                 break;
6958                                         case RENDERPATH_D3D9:
6959                                         case RENDERPATH_D3D10:
6960                                         case RENDERPATH_D3D11:
6961                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6962                                                 break;
6963                                         }
6964                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6965                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6966                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6967                                 }
6968
6969                                 // updates old view angles for next pass
6970                                 VectorCopy(cl.viewangles, blur_oldangles);
6971
6972                                 // copy view into the ghost texture
6973                                 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);
6974                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6975                                 r_fb.ghosttexture_valid = true;
6976                         }
6977                 }
6978                 else
6979                 {
6980                         // no r_fb.colortexture means we're rendering to the real fb
6981                         // we may still have to do view tint...
6982                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6983                         {
6984                                 // apply a color tint to the whole view
6985                                 R_ResetViewRendering2D(0, NULL, NULL);
6986                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6987                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6988                                 R_SetupShader_Generic_NoTexture(false, true);
6989                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6990                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6991                         }
6992                         break; // no screen processing, no bloom, skip it
6993                 }
6994
6995                 if (r_fb.bloomtexture[0])
6996                 {
6997                         // make the bloom texture
6998                         R_Bloom_MakeTexture();
6999                 }
7000
7001 #if _MSC_VER >= 1400
7002 #define sscanf sscanf_s
7003 #endif
7004                 memset(uservecs, 0, sizeof(uservecs));
7005                 if (r_glsl_postprocess_uservec1_enable.integer)
7006                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7007                 if (r_glsl_postprocess_uservec2_enable.integer)
7008                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7009                 if (r_glsl_postprocess_uservec3_enable.integer)
7010                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7011                 if (r_glsl_postprocess_uservec4_enable.integer)
7012                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7013
7014                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
7015                 GL_Color(1, 1, 1, 1);
7016                 GL_BlendFunc(GL_ONE, GL_ZERO);
7017
7018                 switch(vid.renderpath)
7019                 {
7020                 case RENDERPATH_GL20:
7021                 case RENDERPATH_GLES2:
7022                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7023                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7024                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
7025                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
7026                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
7027                         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]);
7028                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7029                         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]);
7030                         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]);
7031                         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]);
7032                         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]);
7033                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7034                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7035                         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);
7036                         break;
7037                 case RENDERPATH_D3D9:
7038 #ifdef SUPPORTD3D
7039                         // 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...
7040                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7041                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
7042                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7043                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7044                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7045                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7046                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7047                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7048                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7049                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7050                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7051                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
7052                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7053                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7054 #endif
7055                         break;
7056                 case RENDERPATH_D3D10:
7057                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7058                         break;
7059                 case RENDERPATH_D3D11:
7060                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7061                         break;
7062                 case RENDERPATH_SOFT:
7063                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7064                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7065                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7066                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7067                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7068                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7069                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7070                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7071                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7072                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7073                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7074                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7075                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7076                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7077                         break;
7078                 default:
7079                         break;
7080                 }
7081                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7082                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7083                 break;
7084         case RENDERPATH_GL11:
7085         case RENDERPATH_GL13:
7086         case RENDERPATH_GLES1:
7087                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7088                 {
7089                         // apply a color tint to the whole view
7090                         R_ResetViewRendering2D(0, NULL, NULL);
7091                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7092                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7093                         R_SetupShader_Generic_NoTexture(false, true);
7094                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7095                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7096                 }
7097                 break;
7098         }
7099 }
7100
7101 matrix4x4_t r_waterscrollmatrix;
7102
7103 void R_UpdateFog(void)
7104 {
7105         // Nehahra fog
7106         if (gamemode == GAME_NEHAHRA)
7107         {
7108                 if (gl_fogenable.integer)
7109                 {
7110                         r_refdef.oldgl_fogenable = true;
7111                         r_refdef.fog_density = gl_fogdensity.value;
7112                         r_refdef.fog_red = gl_fogred.value;
7113                         r_refdef.fog_green = gl_foggreen.value;
7114                         r_refdef.fog_blue = gl_fogblue.value;
7115                         r_refdef.fog_alpha = 1;
7116                         r_refdef.fog_start = 0;
7117                         r_refdef.fog_end = gl_skyclip.value;
7118                         r_refdef.fog_height = 1<<30;
7119                         r_refdef.fog_fadedepth = 128;
7120                 }
7121                 else if (r_refdef.oldgl_fogenable)
7122                 {
7123                         r_refdef.oldgl_fogenable = false;
7124                         r_refdef.fog_density = 0;
7125                         r_refdef.fog_red = 0;
7126                         r_refdef.fog_green = 0;
7127                         r_refdef.fog_blue = 0;
7128                         r_refdef.fog_alpha = 0;
7129                         r_refdef.fog_start = 0;
7130                         r_refdef.fog_end = 0;
7131                         r_refdef.fog_height = 1<<30;
7132                         r_refdef.fog_fadedepth = 128;
7133                 }
7134         }
7135
7136         // fog parms
7137         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7138         r_refdef.fog_start = max(0, r_refdef.fog_start);
7139         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7140
7141         if (r_refdef.fog_density && r_drawfog.integer)
7142         {
7143                 r_refdef.fogenabled = true;
7144                 // this is the point where the fog reaches 0.9986 alpha, which we
7145                 // consider a good enough cutoff point for the texture
7146                 // (0.9986 * 256 == 255.6)
7147                 if (r_fog_exp2.integer)
7148                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7149                 else
7150                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7151                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7152                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7153                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7154                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7155                         R_BuildFogHeightTexture();
7156                 // fog color was already set
7157                 // update the fog texture
7158                 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)
7159                         R_BuildFogTexture();
7160                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7161                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7162         }
7163         else
7164                 r_refdef.fogenabled = false;
7165
7166         // fog color
7167         if (r_refdef.fog_density)
7168         {
7169                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7170                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7171                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7172
7173                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7174                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7175                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7176                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7177
7178                 {
7179                         vec3_t fogvec;
7180                         VectorCopy(r_refdef.fogcolor, fogvec);
7181                         //   color.rgb *= ContrastBoost * SceneBrightness;
7182                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7183                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7184                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7185                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7186                 }
7187         }
7188 }
7189
7190 void R_UpdateVariables(void)
7191 {
7192         R_Textures_Frame();
7193
7194         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7195
7196         r_refdef.farclip = r_farclip_base.value;
7197         if (r_refdef.scene.worldmodel)
7198                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7199         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7200
7201         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7202                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7203         r_refdef.polygonfactor = 0;
7204         r_refdef.polygonoffset = 0;
7205         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7206         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7207
7208         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7209         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7210         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7211         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7212         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7213         if (FAKELIGHT_ENABLED)
7214         {
7215                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7216         }
7217         else if (r_refdef.scene.worldmodel)
7218         {
7219                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7220         }
7221         if (r_showsurfaces.integer)
7222         {
7223                 r_refdef.scene.rtworld = false;
7224                 r_refdef.scene.rtworldshadows = false;
7225                 r_refdef.scene.rtdlight = false;
7226                 r_refdef.scene.rtdlightshadows = false;
7227                 r_refdef.lightmapintensity = 0;
7228         }
7229
7230         r_gpuskeletal = false;
7231         switch(vid.renderpath)
7232         {
7233         case RENDERPATH_GL20:
7234                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7235         case RENDERPATH_D3D9:
7236         case RENDERPATH_D3D10:
7237         case RENDERPATH_D3D11:
7238         case RENDERPATH_SOFT:
7239         case RENDERPATH_GLES2:
7240                 if(!vid_gammatables_trivial)
7241                 {
7242                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7243                         {
7244                                 // build GLSL gamma texture
7245 #define RAMPWIDTH 256
7246                                 unsigned short ramp[RAMPWIDTH * 3];
7247                                 unsigned char rampbgr[RAMPWIDTH][4];
7248                                 int i;
7249
7250                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7251
7252                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7253                                 for(i = 0; i < RAMPWIDTH; ++i)
7254                                 {
7255                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7256                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7257                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7258                                         rampbgr[i][3] = 0;
7259                                 }
7260                                 if (r_texture_gammaramps)
7261                                 {
7262                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7263                                 }
7264                                 else
7265                                 {
7266                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7267                                 }
7268                         }
7269                 }
7270                 else
7271                 {
7272                         // remove GLSL gamma texture
7273                 }
7274                 break;
7275         case RENDERPATH_GL11:
7276         case RENDERPATH_GL13:
7277         case RENDERPATH_GLES1:
7278                 break;
7279         }
7280 }
7281
7282 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7283 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7284 /*
7285 ================
7286 R_SelectScene
7287 ================
7288 */
7289 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7290         if( scenetype != r_currentscenetype ) {
7291                 // store the old scenetype
7292                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7293                 r_currentscenetype = scenetype;
7294                 // move in the new scene
7295                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7296         }
7297 }
7298
7299 /*
7300 ================
7301 R_GetScenePointer
7302 ================
7303 */
7304 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7305 {
7306         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7307         if( scenetype == r_currentscenetype ) {
7308                 return &r_refdef.scene;
7309         } else {
7310                 return &r_scenes_store[ scenetype ];
7311         }
7312 }
7313
7314 static int R_SortEntities_Compare(const void *ap, const void *bp)
7315 {
7316         const entity_render_t *a = *(const entity_render_t **)ap;
7317         const entity_render_t *b = *(const entity_render_t **)bp;
7318
7319         // 1. compare model
7320         if(a->model < b->model)
7321                 return -1;
7322         if(a->model > b->model)
7323                 return +1;
7324
7325         // 2. compare skin
7326         // TODO possibly calculate the REAL skinnum here first using
7327         // skinscenes?
7328         if(a->skinnum < b->skinnum)
7329                 return -1;
7330         if(a->skinnum > b->skinnum)
7331                 return +1;
7332
7333         // everything we compared is equal
7334         return 0;
7335 }
7336 static void R_SortEntities(void)
7337 {
7338         // below or equal 2 ents, sorting never gains anything
7339         if(r_refdef.scene.numentities <= 2)
7340                 return;
7341         // sort
7342         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7343 }
7344
7345 /*
7346 ================
7347 R_RenderView
7348 ================
7349 */
7350 int dpsoftrast_test;
7351 extern cvar_t r_shadow_bouncegrid;
7352 void R_RenderView(void)
7353 {
7354         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7355         int fbo;
7356         rtexture_t *depthtexture;
7357         rtexture_t *colortexture;
7358
7359         dpsoftrast_test = r_test.integer;
7360
7361         if (r_timereport_active)
7362                 R_TimeReport("start");
7363         r_textureframe++; // used only by R_GetCurrentTexture
7364         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7365
7366         if(R_CompileShader_CheckStaticParms())
7367                 R_GLSL_Restart_f();
7368
7369         if (!r_drawentities.integer)
7370                 r_refdef.scene.numentities = 0;
7371         else if (r_sortentities.integer)
7372                 R_SortEntities();
7373
7374         R_AnimCache_ClearCache();
7375
7376         /* adjust for stereo display */
7377         if(R_Stereo_Active())
7378         {
7379                 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);
7380                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7381         }
7382
7383         if (r_refdef.view.isoverlay)
7384         {
7385                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7386                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7387                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7388                 R_TimeReport("depthclear");
7389
7390                 r_refdef.view.showdebug = false;
7391
7392                 r_fb.water.enabled = false;
7393                 r_fb.water.numwaterplanes = 0;
7394
7395                 R_RenderScene(0, NULL, NULL);
7396
7397                 r_refdef.view.matrix = originalmatrix;
7398
7399                 CHECKGLERROR
7400                 return;
7401         }
7402
7403         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7404         {
7405                 r_refdef.view.matrix = originalmatrix;
7406                 return;
7407         }
7408
7409         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7410
7411         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7412                 // in sRGB fallback, behave similar to true sRGB: convert this
7413                 // value from linear to sRGB
7414                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7415
7416         R_RenderView_UpdateViewVectors();
7417
7418         R_Shadow_UpdateWorldLightSelection();
7419
7420         R_Bloom_StartFrame();
7421
7422         // apply bloom brightness offset
7423         if(r_fb.bloomtexture[0])
7424                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7425
7426         R_Water_StartFrame();
7427
7428         // now we probably have an fbo to render into
7429         fbo = r_fb.fbo;
7430         depthtexture = r_fb.depthtexture;
7431         colortexture = r_fb.colortexture;
7432
7433         CHECKGLERROR
7434         if (r_timereport_active)
7435                 R_TimeReport("viewsetup");
7436
7437         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7438
7439         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7440         {
7441                 R_ClearScreen(r_refdef.fogenabled);
7442                 if (r_timereport_active)
7443                         R_TimeReport("viewclear");
7444         }
7445         r_refdef.view.clear = true;
7446
7447         r_refdef.view.showdebug = true;
7448
7449         R_View_Update();
7450         if (r_timereport_active)
7451                 R_TimeReport("visibility");
7452
7453         R_AnimCache_CacheVisibleEntities();
7454         if (r_timereport_active)
7455                 R_TimeReport("animcache");
7456
7457         R_Shadow_UpdateBounceGridTexture();
7458         if (r_timereport_active && r_shadow_bouncegrid.integer)
7459                 R_TimeReport("bouncegrid");
7460
7461         r_fb.water.numwaterplanes = 0;
7462         if (r_fb.water.enabled)
7463                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7464
7465         R_RenderScene(fbo, depthtexture, colortexture);
7466         r_fb.water.numwaterplanes = 0;
7467
7468         R_BlendView(fbo, depthtexture, colortexture);
7469         if (r_timereport_active)
7470                 R_TimeReport("blendview");
7471
7472         GL_Scissor(0, 0, vid.width, vid.height);
7473         GL_ScissorTest(false);
7474
7475         r_refdef.view.matrix = originalmatrix;
7476
7477         CHECKGLERROR
7478 }
7479
7480 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7481 {
7482         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7483         {
7484                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7485                 if (r_timereport_active)
7486                         R_TimeReport("waterworld");
7487         }
7488
7489         // don't let sound skip if going slow
7490         if (r_refdef.scene.extraupdate)
7491                 S_ExtraUpdate ();
7492
7493         R_DrawModelsAddWaterPlanes();
7494         if (r_timereport_active)
7495                 R_TimeReport("watermodels");
7496
7497         if (r_fb.water.numwaterplanes)
7498         {
7499                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7500                 if (r_timereport_active)
7501                         R_TimeReport("waterscenes");
7502         }
7503 }
7504
7505 extern cvar_t cl_locs_show;
7506 static void R_DrawLocs(void);
7507 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7508 static void R_DrawModelDecals(void);
7509 extern cvar_t cl_decals_newsystem;
7510 extern qboolean r_shadow_usingdeferredprepass;
7511 extern int r_shadow_shadowmapatlas_modelshadows_size;
7512 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7513 {
7514         qboolean shadowmapping = false;
7515
7516         if (r_timereport_active)
7517                 R_TimeReport("beginscene");
7518
7519         r_refdef.stats[r_stat_renders]++;
7520
7521         R_UpdateFog();
7522
7523         // don't let sound skip if going slow
7524         if (r_refdef.scene.extraupdate)
7525                 S_ExtraUpdate ();
7526
7527         R_MeshQueue_BeginScene();
7528
7529         R_SkyStartFrame();
7530
7531         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);
7532
7533         if (r_timereport_active)
7534                 R_TimeReport("skystartframe");
7535
7536         if (cl.csqc_vidvars.drawworld)
7537         {
7538                 // don't let sound skip if going slow
7539                 if (r_refdef.scene.extraupdate)
7540                         S_ExtraUpdate ();
7541
7542                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7543                 {
7544                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7545                         if (r_timereport_active)
7546                                 R_TimeReport("worldsky");
7547                 }
7548
7549                 if (R_DrawBrushModelsSky() && r_timereport_active)
7550                         R_TimeReport("bmodelsky");
7551
7552                 if (skyrendermasked && skyrenderlater)
7553                 {
7554                         // we have to force off the water clipping plane while rendering sky
7555                         R_SetupView(false, fbo, depthtexture, colortexture);
7556                         R_Sky();
7557                         R_SetupView(true, fbo, depthtexture, colortexture);
7558                         if (r_timereport_active)
7559                                 R_TimeReport("sky");
7560                 }
7561         }
7562
7563         R_Shadow_PrepareModelShadows();
7564         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7565         if (r_timereport_active)
7566                 R_TimeReport("preparelights");
7567
7568         // render all the shadowmaps that will be used for this view
7569         shadowmapping = R_Shadow_ShadowMappingEnabled();
7570         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7571         {
7572                 R_Shadow_DrawShadowMaps();
7573                 if (r_timereport_active)
7574                         R_TimeReport("shadowmaps");
7575         }
7576
7577         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7578         if (r_shadow_usingdeferredprepass)
7579                 R_Shadow_DrawPrepass();
7580
7581         // now we begin the forward pass of the view render
7582         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7583         {
7584                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7585                 if (r_timereport_active)
7586                         R_TimeReport("worlddepth");
7587         }
7588         if (r_depthfirst.integer >= 2)
7589         {
7590                 R_DrawModelsDepth();
7591                 if (r_timereport_active)
7592                         R_TimeReport("modeldepth");
7593         }
7594
7595         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7596         {
7597                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7598                 if (r_timereport_active)
7599                         R_TimeReport("world");
7600         }
7601
7602         // don't let sound skip if going slow
7603         if (r_refdef.scene.extraupdate)
7604                 S_ExtraUpdate ();
7605
7606         R_DrawModels();
7607         if (r_timereport_active)
7608                 R_TimeReport("models");
7609
7610         // don't let sound skip if going slow
7611         if (r_refdef.scene.extraupdate)
7612                 S_ExtraUpdate ();
7613
7614         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7615         {
7616                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7617                 R_Shadow_DrawModelShadows();
7618                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7619                 // don't let sound skip if going slow
7620                 if (r_refdef.scene.extraupdate)
7621                         S_ExtraUpdate ();
7622         }
7623
7624         if (!r_shadow_usingdeferredprepass)
7625         {
7626                 R_Shadow_DrawLights();
7627                 if (r_timereport_active)
7628                         R_TimeReport("rtlights");
7629         }
7630
7631         // don't let sound skip if going slow
7632         if (r_refdef.scene.extraupdate)
7633                 S_ExtraUpdate ();
7634
7635         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7636         {
7637                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7638                 R_Shadow_DrawModelShadows();
7639                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7640                 // don't let sound skip if going slow
7641                 if (r_refdef.scene.extraupdate)
7642                         S_ExtraUpdate ();
7643         }
7644
7645         if (cl.csqc_vidvars.drawworld)
7646         {
7647                 if (cl_decals_newsystem.integer)
7648                 {
7649                         R_DrawModelDecals();
7650                         if (r_timereport_active)
7651                                 R_TimeReport("modeldecals");
7652                 }
7653                 else
7654                 {
7655                         R_DrawDecals();
7656                         if (r_timereport_active)
7657                                 R_TimeReport("decals");
7658                 }
7659
7660                 R_DrawParticles();
7661                 if (r_timereport_active)
7662                         R_TimeReport("particles");
7663
7664                 R_DrawExplosions();
7665                 if (r_timereport_active)
7666                         R_TimeReport("explosions");
7667         }
7668
7669         if (cl.csqc_loaded)
7670                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7671
7672         if (r_refdef.view.showdebug)
7673         {
7674                 if (cl_locs_show.integer)
7675                 {
7676                         R_DrawLocs();
7677                         if (r_timereport_active)
7678                                 R_TimeReport("showlocs");
7679                 }
7680
7681                 if (r_drawportals.integer)
7682                 {
7683                         R_DrawPortals();
7684                         if (r_timereport_active)
7685                                 R_TimeReport("portals");
7686                 }
7687
7688                 if (r_showbboxes_client.value > 0)
7689                 {
7690                         R_DrawEntityBBoxes(CLVM_prog);
7691                         if (r_timereport_active)
7692                                 R_TimeReport("clbboxes");
7693                 }
7694                 if (r_showbboxes.value > 0)
7695                 {
7696                         R_DrawEntityBBoxes(SVVM_prog);
7697                         if (r_timereport_active)
7698                                 R_TimeReport("svbboxes");
7699                 }
7700         }
7701
7702         if (r_transparent.integer)
7703         {
7704                 R_MeshQueue_RenderTransparent();
7705                 if (r_timereport_active)
7706                         R_TimeReport("drawtrans");
7707         }
7708
7709         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))
7710         {
7711                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7712                 if (r_timereport_active)
7713                         R_TimeReport("worlddebug");
7714                 R_DrawModelsDebug();
7715                 if (r_timereport_active)
7716                         R_TimeReport("modeldebug");
7717         }
7718
7719         if (cl.csqc_vidvars.drawworld)
7720         {
7721                 R_Shadow_DrawCoronas();
7722                 if (r_timereport_active)
7723                         R_TimeReport("coronas");
7724         }
7725
7726 #if 0
7727         {
7728                 GL_DepthTest(false);
7729                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7730                 GL_Color(1, 1, 1, 1);
7731                 qglBegin(GL_POLYGON);
7732                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7733                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7734                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7735                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7736                 qglEnd();
7737                 qglBegin(GL_POLYGON);
7738                 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]);
7739                 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]);
7740                 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]);
7741                 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]);
7742                 qglEnd();
7743                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7744         }
7745 #endif
7746
7747         // don't let sound skip if going slow
7748         if (r_refdef.scene.extraupdate)
7749                 S_ExtraUpdate ();
7750 }
7751
7752 static const unsigned short bboxelements[36] =
7753 {
7754         5, 1, 3, 5, 3, 7,
7755         6, 2, 0, 6, 0, 4,
7756         7, 3, 2, 7, 2, 6,
7757         4, 0, 1, 4, 1, 5,
7758         4, 5, 7, 4, 7, 6,
7759         1, 0, 2, 1, 2, 3,
7760 };
7761
7762 #define BBOXEDGES 13
7763 static const float bboxedges[BBOXEDGES][6] = 
7764 {
7765         // whole box
7766         { 0, 0, 0, 1, 1, 1 },
7767         // bottom edges
7768         { 0, 0, 0, 0, 1, 0 },
7769         { 0, 0, 0, 1, 0, 0 },
7770         { 0, 1, 0, 1, 1, 0 },
7771         { 1, 0, 0, 1, 1, 0 },
7772         // top edges
7773         { 0, 0, 1, 0, 1, 1 },
7774         { 0, 0, 1, 1, 0, 1 },
7775         { 0, 1, 1, 1, 1, 1 },
7776         { 1, 0, 1, 1, 1, 1 },
7777         // vertical edges
7778         { 0, 0, 0, 0, 0, 1 },
7779         { 1, 0, 0, 1, 0, 1 },
7780         { 0, 1, 0, 0, 1, 1 },
7781         { 1, 1, 0, 1, 1, 1 },
7782 };
7783
7784 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7785 {
7786         int numvertices = BBOXEDGES * 8;
7787         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7788         int numtriangles = BBOXEDGES * 12;
7789         unsigned short elements[BBOXEDGES * 36];
7790         int i, edge;
7791         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7792
7793         RSurf_ActiveWorldEntity();
7794
7795         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7796         GL_DepthMask(false);
7797         GL_DepthRange(0, 1);
7798         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7799
7800         for (edge = 0; edge < BBOXEDGES; edge++)
7801         {
7802                 for (i = 0; i < 3; i++)
7803                 {
7804                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7805                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7806                 }
7807                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7808                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7809                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7810                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7811                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7812                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7813                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7814                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7815                 for (i = 0; i < 36; i++)
7816                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7817         }
7818         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7819         if (r_refdef.fogenabled)
7820         {
7821                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7822                 {
7823                         f1 = RSurf_FogVertex(v);
7824                         f2 = 1 - f1;
7825                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7826                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7827                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7828                 }
7829         }
7830         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7831         R_Mesh_ResetTextureState();
7832         R_SetupShader_Generic_NoTexture(false, false);
7833         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7834 }
7835
7836 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7837 {
7838         // hacky overloading of the parameters
7839         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7840         int i;
7841         float color[4];
7842         prvm_edict_t *edict;
7843
7844         GL_CullFace(GL_NONE);
7845         R_SetupShader_Generic_NoTexture(false, false);
7846
7847         for (i = 0;i < numsurfaces;i++)
7848         {
7849                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7850                 switch ((int)PRVM_serveredictfloat(edict, solid))
7851                 {
7852                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7853                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7854                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7855                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7856                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7857                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7858                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7859                 }
7860                 if (prog == CLVM_prog)
7861                         color[3] *= r_showbboxes_client.value;
7862                 else
7863                         color[3] *= r_showbboxes.value;
7864                 color[3] = bound(0, color[3], 1);
7865                 GL_DepthTest(!r_showdisabledepthtest.integer);
7866                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7867         }
7868 }
7869
7870 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7871 {
7872         int i;
7873         prvm_edict_t *edict;
7874         vec3_t center;
7875
7876         if (prog == NULL)
7877                 return;
7878
7879         for (i = 0; i < prog->num_edicts; i++)
7880         {
7881                 edict = PRVM_EDICT_NUM(i);
7882                 if (edict->priv.server->free)
7883                         continue;
7884                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7885                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7886                         continue;
7887                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7888                         continue;
7889                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7890                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7891         }
7892 }
7893
7894 static const int nomodelelement3i[24] =
7895 {
7896         5, 2, 0,
7897         5, 1, 2,
7898         5, 0, 3,
7899         5, 3, 1,
7900         0, 2, 4,
7901         2, 1, 4,
7902         3, 0, 4,
7903         1, 3, 4
7904 };
7905
7906 static const unsigned short nomodelelement3s[24] =
7907 {
7908         5, 2, 0,
7909         5, 1, 2,
7910         5, 0, 3,
7911         5, 3, 1,
7912         0, 2, 4,
7913         2, 1, 4,
7914         3, 0, 4,
7915         1, 3, 4
7916 };
7917
7918 static const float nomodelvertex3f[6*3] =
7919 {
7920         -16,   0,   0,
7921          16,   0,   0,
7922           0, -16,   0,
7923           0,  16,   0,
7924           0,   0, -16,
7925           0,   0,  16
7926 };
7927
7928 static const float nomodelcolor4f[6*4] =
7929 {
7930         0.0f, 0.0f, 0.5f, 1.0f,
7931         0.0f, 0.0f, 0.5f, 1.0f,
7932         0.0f, 0.5f, 0.0f, 1.0f,
7933         0.0f, 0.5f, 0.0f, 1.0f,
7934         0.5f, 0.0f, 0.0f, 1.0f,
7935         0.5f, 0.0f, 0.0f, 1.0f
7936 };
7937
7938 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7939 {
7940         int i;
7941         float f1, f2, *c;
7942         float color4f[6*4];
7943
7944         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);
7945
7946         // this is only called once per entity so numsurfaces is always 1, and
7947         // surfacelist is always {0}, so this code does not handle batches
7948
7949         if (rsurface.ent_flags & RENDER_ADDITIVE)
7950         {
7951                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7952                 GL_DepthMask(false);
7953         }
7954         else if (rsurface.colormod[3] < 1)
7955         {
7956                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7957                 GL_DepthMask(false);
7958         }
7959         else
7960         {
7961                 GL_BlendFunc(GL_ONE, GL_ZERO);
7962                 GL_DepthMask(true);
7963         }
7964         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7965         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7966         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7967         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7968         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7969         for (i = 0, c = color4f;i < 6;i++, c += 4)
7970         {
7971                 c[0] *= rsurface.colormod[0];
7972                 c[1] *= rsurface.colormod[1];
7973                 c[2] *= rsurface.colormod[2];
7974                 c[3] *= rsurface.colormod[3];
7975         }
7976         if (r_refdef.fogenabled)
7977         {
7978                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7979                 {
7980                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7981                         f2 = 1 - f1;
7982                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7983                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7984                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7985                 }
7986         }
7987 //      R_Mesh_ResetTextureState();
7988         R_SetupShader_Generic_NoTexture(false, false);
7989         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7990         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7991 }
7992
7993 void R_DrawNoModel(entity_render_t *ent)
7994 {
7995         vec3_t org;
7996         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7997         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7998                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7999         else
8000                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8001 }
8002
8003 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
8004 {
8005         vec3_t right1, right2, diff, normal;
8006
8007         VectorSubtract (org2, org1, normal);
8008
8009         // calculate 'right' vector for start
8010         VectorSubtract (r_refdef.view.origin, org1, diff);
8011         CrossProduct (normal, diff, right1);
8012         VectorNormalize (right1);
8013
8014         // calculate 'right' vector for end
8015         VectorSubtract (r_refdef.view.origin, org2, diff);
8016         CrossProduct (normal, diff, right2);
8017         VectorNormalize (right2);
8018
8019         vert[ 0] = org1[0] + width * right1[0];
8020         vert[ 1] = org1[1] + width * right1[1];
8021         vert[ 2] = org1[2] + width * right1[2];
8022         vert[ 3] = org1[0] - width * right1[0];
8023         vert[ 4] = org1[1] - width * right1[1];
8024         vert[ 5] = org1[2] - width * right1[2];
8025         vert[ 6] = org2[0] - width * right2[0];
8026         vert[ 7] = org2[1] - width * right2[1];
8027         vert[ 8] = org2[2] - width * right2[2];
8028         vert[ 9] = org2[0] + width * right2[0];
8029         vert[10] = org2[1] + width * right2[1];
8030         vert[11] = org2[2] + width * right2[2];
8031 }
8032
8033 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)
8034 {
8035         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8036         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8037         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8038         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8039         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8040         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8041         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8042         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8043         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8044         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8045         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8046         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8047 }
8048
8049 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8050 {
8051         int i;
8052         float *vertex3f;
8053         float v[3];
8054         VectorSet(v, x, y, z);
8055         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8056                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8057                         break;
8058         if (i == mesh->numvertices)
8059         {
8060                 if (mesh->numvertices < mesh->maxvertices)
8061                 {
8062                         VectorCopy(v, vertex3f);
8063                         mesh->numvertices++;
8064                 }
8065                 return mesh->numvertices;
8066         }
8067         else
8068                 return i;
8069 }
8070
8071 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8072 {
8073         int i;
8074         int *e, element[3];
8075         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8076         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8077         e = mesh->element3i + mesh->numtriangles * 3;
8078         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8079         {
8080                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8081                 if (mesh->numtriangles < mesh->maxtriangles)
8082                 {
8083                         *e++ = element[0];
8084                         *e++ = element[1];
8085                         *e++ = element[2];
8086                         mesh->numtriangles++;
8087                 }
8088                 element[1] = element[2];
8089         }
8090 }
8091
8092 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8093 {
8094         int i;
8095         int *e, element[3];
8096         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8097         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8098         e = mesh->element3i + mesh->numtriangles * 3;
8099         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8100         {
8101                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8102                 if (mesh->numtriangles < mesh->maxtriangles)
8103                 {
8104                         *e++ = element[0];
8105                         *e++ = element[1];
8106                         *e++ = element[2];
8107                         mesh->numtriangles++;
8108                 }
8109                 element[1] = element[2];
8110         }
8111 }
8112
8113 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8114 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8115 {
8116         int planenum, planenum2;
8117         int w;
8118         int tempnumpoints;
8119         mplane_t *plane, *plane2;
8120         double maxdist;
8121         double temppoints[2][256*3];
8122         // figure out how large a bounding box we need to properly compute this brush
8123         maxdist = 0;
8124         for (w = 0;w < numplanes;w++)
8125                 maxdist = max(maxdist, fabs(planes[w].dist));
8126         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8127         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8128         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8129         {
8130                 w = 0;
8131                 tempnumpoints = 4;
8132                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8133                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8134                 {
8135                         if (planenum2 == planenum)
8136                                 continue;
8137                         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);
8138                         w = !w;
8139                 }
8140                 if (tempnumpoints < 3)
8141                         continue;
8142                 // generate elements forming a triangle fan for this polygon
8143                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8144         }
8145 }
8146
8147 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)
8148 {
8149         texturelayer_t *layer;
8150         layer = t->currentlayers + t->currentnumlayers++;
8151         layer->type = type;
8152         layer->depthmask = depthmask;
8153         layer->blendfunc1 = blendfunc1;
8154         layer->blendfunc2 = blendfunc2;
8155         layer->texture = texture;
8156         layer->texmatrix = *matrix;
8157         layer->color[0] = r;
8158         layer->color[1] = g;
8159         layer->color[2] = b;
8160         layer->color[3] = a;
8161 }
8162
8163 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8164 {
8165         if(parms[0] == 0 && parms[1] == 0)
8166                 return false;
8167         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8168                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8169                         return false;
8170         return true;
8171 }
8172
8173 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8174 {
8175         double index, f;
8176         index = parms[2] + rsurface.shadertime * parms[3];
8177         index -= floor(index);
8178         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8179         {
8180         default:
8181         case Q3WAVEFUNC_NONE:
8182         case Q3WAVEFUNC_NOISE:
8183         case Q3WAVEFUNC_COUNT:
8184                 f = 0;
8185                 break;
8186         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8187         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8188         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8189         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8190         case Q3WAVEFUNC_TRIANGLE:
8191                 index *= 4;
8192                 f = index - floor(index);
8193                 if (index < 1)
8194                 {
8195                         // f = f;
8196                 }
8197                 else if (index < 2)
8198                         f = 1 - f;
8199                 else if (index < 3)
8200                         f = -f;
8201                 else
8202                         f = -(1 - f);
8203                 break;
8204         }
8205         f = parms[0] + parms[1] * f;
8206         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8207                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8208         return (float) f;
8209 }
8210
8211 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8212 {
8213         int w, h, idx;
8214         float shadertime;
8215         float f;
8216         float offsetd[2];
8217         float tcmat[12];
8218         matrix4x4_t matrix, temp;
8219         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8220         // it's better to have one huge fixup every 9 hours than gradual
8221         // degradation over time which looks consistently bad after many hours.
8222         //
8223         // tcmod scroll in particular suffers from this degradation which can't be
8224         // effectively worked around even with floor() tricks because we don't
8225         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8226         // a workaround involving floor() would be incorrect anyway...
8227         shadertime = rsurface.shadertime;
8228         if (shadertime >= 32768.0f)
8229                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8230         switch(tcmod->tcmod)
8231         {
8232                 case Q3TCMOD_COUNT:
8233                 case Q3TCMOD_NONE:
8234                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8235                                 matrix = r_waterscrollmatrix;
8236                         else
8237                                 matrix = identitymatrix;
8238                         break;
8239                 case Q3TCMOD_ENTITYTRANSLATE:
8240                         // this is used in Q3 to allow the gamecode to control texcoord
8241                         // scrolling on the entity, which is not supported in darkplaces yet.
8242                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8243                         break;
8244                 case Q3TCMOD_ROTATE:
8245                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8246                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8247                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8248                         break;
8249                 case Q3TCMOD_SCALE:
8250                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8251                         break;
8252                 case Q3TCMOD_SCROLL:
8253                         // this particular tcmod is a "bug for bug" compatible one with regards to
8254                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8255                         // specifically did the wrapping and so we must mimic that...
8256                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8257                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8258                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8259                         break;
8260                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8261                         w = (int) tcmod->parms[0];
8262                         h = (int) tcmod->parms[1];
8263                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8264                         f = f - floor(f);
8265                         idx = (int) floor(f * w * h);
8266                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8267                         break;
8268                 case Q3TCMOD_STRETCH:
8269                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8270                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8271                         break;
8272                 case Q3TCMOD_TRANSFORM:
8273                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8274                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8275                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8276                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8277                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8278                         break;
8279                 case Q3TCMOD_TURBULENT:
8280                         // this is handled in the RSurf_PrepareVertices function
8281                         matrix = identitymatrix;
8282                         break;
8283         }
8284         temp = *texmatrix;
8285         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8286 }
8287
8288 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8289 {
8290         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8291         char name[MAX_QPATH];
8292         skinframe_t *skinframe;
8293         unsigned char pixels[296*194];
8294         strlcpy(cache->name, skinname, sizeof(cache->name));
8295         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8296         if (developer_loading.integer)
8297                 Con_Printf("loading %s\n", name);
8298         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8299         if (!skinframe || !skinframe->base)
8300         {
8301                 unsigned char *f;
8302                 fs_offset_t filesize;
8303                 skinframe = NULL;
8304                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8305                 if (f)
8306                 {
8307                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8308                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8309                         Mem_Free(f);
8310                 }
8311         }
8312         cache->skinframe = skinframe;
8313 }
8314
8315 texture_t *R_GetCurrentTexture(texture_t *t)
8316 {
8317         int i;
8318         const entity_render_t *ent = rsurface.entity;
8319         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8320         q3shaderinfo_layer_tcmod_t *tcmod;
8321
8322         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8323                 return t->currentframe;
8324         t->update_lastrenderframe = r_textureframe;
8325         t->update_lastrenderentity = (void *)ent;
8326
8327         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8328                 t->camera_entity = ent->entitynumber;
8329         else
8330                 t->camera_entity = 0;
8331
8332         // switch to an alternate material if this is a q1bsp animated material
8333         {
8334                 texture_t *texture = t;
8335                 int s = rsurface.ent_skinnum;
8336                 if ((unsigned int)s >= (unsigned int)model->numskins)
8337                         s = 0;
8338                 if (model->skinscenes)
8339                 {
8340                         if (model->skinscenes[s].framecount > 1)
8341                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8342                         else
8343                                 s = model->skinscenes[s].firstframe;
8344                 }
8345                 if (s > 0)
8346                         t = t + s * model->num_surfaces;
8347                 if (t->animated)
8348                 {
8349                         // use an alternate animation if the entity's frame is not 0,
8350                         // and only if the texture has an alternate animation
8351                         if (t->animated == 2) // q2bsp
8352                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8353                         else if (rsurface.ent_alttextures && t->anim_total[1])
8354                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8355                         else
8356                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8357                 }
8358                 texture->currentframe = t;
8359         }
8360
8361         // update currentskinframe to be a qw skin or animation frame
8362         if (rsurface.ent_qwskin >= 0)
8363         {
8364                 i = rsurface.ent_qwskin;
8365                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8366                 {
8367                         r_qwskincache_size = cl.maxclients;
8368                         if (r_qwskincache)
8369                                 Mem_Free(r_qwskincache);
8370                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8371                 }
8372                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8373                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8374                 t->currentskinframe = r_qwskincache[i].skinframe;
8375                 if (t->materialshaderpass && t->currentskinframe == NULL)
8376                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8377         }
8378         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8379                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8380         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8381                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8382
8383         t->currentmaterialflags = t->basematerialflags;
8384         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8385         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8386                 t->currentalpha *= r_wateralpha.value;
8387         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8388                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8389         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8390                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8391         if (!(rsurface.ent_flags & RENDER_LIGHT))
8392                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8393         else if (FAKELIGHT_ENABLED)
8394         {
8395                 // no modellight if using fakelight for the map
8396         }
8397         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8398         {
8399                 // pick a model lighting mode
8400                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8401                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8402                 else
8403                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8404         }
8405         if (rsurface.ent_flags & RENDER_ADDITIVE)
8406                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8407         else if (t->currentalpha < 1)
8408                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8409         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8410         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8411                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8412         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8413                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8414         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8415                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8416         if (t->backgroundshaderpass)
8417                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8418         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8419         {
8420                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8421                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8422         }
8423         else
8424                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8425         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8426         {
8427                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8428                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8429         }
8430         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8431                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8432
8433         // there is no tcmod
8434         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8435         {
8436                 t->currenttexmatrix = r_waterscrollmatrix;
8437                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8438         }
8439         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8440         {
8441                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8442                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8443         }
8444
8445         if (t->materialshaderpass)
8446                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8447                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8448
8449         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8450         if (t->currentskinframe->qpixels)
8451                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8452         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8453         if (!t->basetexture)
8454                 t->basetexture = r_texture_notexture;
8455         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8456         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8457         t->nmaptexture = t->currentskinframe->nmap;
8458         if (!t->nmaptexture)
8459                 t->nmaptexture = r_texture_blanknormalmap;
8460         t->glosstexture = r_texture_black;
8461         t->glowtexture = t->currentskinframe->glow;
8462         t->fogtexture = t->currentskinframe->fog;
8463         t->reflectmasktexture = t->currentskinframe->reflect;
8464         if (t->backgroundshaderpass)
8465         {
8466                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8467                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8468                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8469                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8470                 t->backgroundglosstexture = r_texture_black;
8471                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8472                 if (!t->backgroundnmaptexture)
8473                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8474                 // make sure that if glow is going to be used, both textures are not NULL
8475                 if (!t->backgroundglowtexture && t->glowtexture)
8476                         t->backgroundglowtexture = r_texture_black;
8477                 if (!t->glowtexture && t->backgroundglowtexture)
8478                         t->glowtexture = r_texture_black;
8479         }
8480         else
8481         {
8482                 t->backgroundbasetexture = r_texture_white;
8483                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8484                 t->backgroundglosstexture = r_texture_black;
8485                 t->backgroundglowtexture = NULL;
8486         }
8487         t->specularpower = r_shadow_glossexponent.value;
8488         // TODO: store reference values for these in the texture?
8489         t->specularscale = 0;
8490         if (r_shadow_gloss.integer > 0)
8491         {
8492                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8493                 {
8494                         if (r_shadow_glossintensity.value > 0)
8495                         {
8496                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8497                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8498                                 t->specularscale = r_shadow_glossintensity.value;
8499                         }
8500                 }
8501                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8502                 {
8503                         t->glosstexture = r_texture_white;
8504                         t->backgroundglosstexture = r_texture_white;
8505                         t->specularscale = r_shadow_gloss2intensity.value;
8506                         t->specularpower = r_shadow_gloss2exponent.value;
8507                 }
8508         }
8509         t->specularscale *= t->specularscalemod;
8510         t->specularpower *= t->specularpowermod;
8511         t->rtlightambient = 0;
8512
8513         // lightmaps mode looks bad with dlights using actual texturing, so turn
8514         // off the colormap and glossmap, but leave the normalmap on as it still
8515         // accurately represents the shading involved
8516         if (gl_lightmaps.integer)
8517         {
8518                 t->basetexture = r_texture_grey128;
8519                 t->pantstexture = r_texture_black;
8520                 t->shirttexture = r_texture_black;
8521                 if (gl_lightmaps.integer < 2)
8522                         t->nmaptexture = r_texture_blanknormalmap;
8523                 t->glosstexture = r_texture_black;
8524                 t->glowtexture = NULL;
8525                 t->fogtexture = NULL;
8526                 t->reflectmasktexture = NULL;
8527                 t->backgroundbasetexture = NULL;
8528                 if (gl_lightmaps.integer < 2)
8529                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8530                 t->backgroundglosstexture = r_texture_black;
8531                 t->backgroundglowtexture = NULL;
8532                 t->specularscale = 0;
8533                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8534         }
8535
8536         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8537         VectorClear(t->dlightcolor);
8538         t->currentnumlayers = 0;
8539         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8540         {
8541                 int blendfunc1, blendfunc2;
8542                 qboolean depthmask;
8543                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8544                 {
8545                         blendfunc1 = GL_SRC_ALPHA;
8546                         blendfunc2 = GL_ONE;
8547                 }
8548                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8549                 {
8550                         blendfunc1 = GL_SRC_ALPHA;
8551                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8552                 }
8553                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8554                 {
8555                         blendfunc1 = t->customblendfunc[0];
8556                         blendfunc2 = t->customblendfunc[1];
8557                 }
8558                 else
8559                 {
8560                         blendfunc1 = GL_ONE;
8561                         blendfunc2 = GL_ZERO;
8562                 }
8563                 // don't colormod evilblend textures
8564                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8565                         VectorSet(t->lightmapcolor, 1, 1, 1);
8566                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8567                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8568                 {
8569                         // fullbright is not affected by r_refdef.lightmapintensity
8570                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8571                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8572                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8573                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8574                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8575                 }
8576                 else
8577                 {
8578                         vec3_t ambientcolor;
8579                         float colorscale;
8580                         // set the color tint used for lights affecting this surface
8581                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8582                         colorscale = 2;
8583                         // q3bsp has no lightmap updates, so the lightstylevalue that
8584                         // would normally be baked into the lightmap must be
8585                         // applied to the color
8586                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8587                         if (model->type == mod_brushq3)
8588                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8589                         colorscale *= r_refdef.lightmapintensity;
8590                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8591                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8592                         // basic lit geometry
8593                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8594                         // add pants/shirt if needed
8595                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8596                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8597                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8598                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8599                         // now add ambient passes if needed
8600                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8601                         {
8602                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8603                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8604                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8605                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8606                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8607                         }
8608                 }
8609                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8610                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8611                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8612                 {
8613                         // if this is opaque use alpha blend which will darken the earlier
8614                         // passes cheaply.
8615                         //
8616                         // if this is an alpha blended material, all the earlier passes
8617                         // were darkened by fog already, so we only need to add the fog
8618                         // color ontop through the fog mask texture
8619                         //
8620                         // if this is an additive blended material, all the earlier passes
8621                         // were darkened by fog already, and we should not add fog color
8622                         // (because the background was not darkened, there is no fog color
8623                         // that was lost behind it).
8624                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8625                 }
8626         }
8627
8628         return t;
8629 }
8630
8631 rsurfacestate_t rsurface;
8632
8633 void RSurf_ActiveWorldEntity(void)
8634 {
8635         dp_model_t *model = r_refdef.scene.worldmodel;
8636         //if (rsurface.entity == r_refdef.scene.worldentity)
8637         //      return;
8638         rsurface.entity = r_refdef.scene.worldentity;
8639         rsurface.skeleton = NULL;
8640         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8641         rsurface.ent_skinnum = 0;
8642         rsurface.ent_qwskin = -1;
8643         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8644         rsurface.shadertime = r_refdef.scene.time;
8645         rsurface.matrix = identitymatrix;
8646         rsurface.inversematrix = identitymatrix;
8647         rsurface.matrixscale = 1;
8648         rsurface.inversematrixscale = 1;
8649         R_EntityMatrix(&identitymatrix);
8650         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8651         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8652         rsurface.fograngerecip = r_refdef.fograngerecip;
8653         rsurface.fogheightfade = r_refdef.fogheightfade;
8654         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8655         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8656         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8657         {
8658                 R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir);
8659                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8660         }
8661         else
8662         {
8663                 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8664                 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8665                 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8666         }
8667         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8668         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8669         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8670         rsurface.colormod[3] = 1;
8671         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8672         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8673         rsurface.frameblend[0].lerp = 1;
8674         rsurface.ent_alttextures = false;
8675         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8676         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8677         rsurface.entityskeletaltransform3x4 = NULL;
8678         rsurface.entityskeletaltransform3x4buffer = NULL;
8679         rsurface.entityskeletaltransform3x4offset = 0;
8680         rsurface.entityskeletaltransform3x4size = 0;;
8681         rsurface.entityskeletalnumtransforms = 0;
8682         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8683         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8684         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8685         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8686         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8687         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8688         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8689         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8690         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8691         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8692         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8693         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8694         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8695         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8696         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8697         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8698         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8699         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8700         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8701         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8702         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8703         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8704         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8705         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8706         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8707         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8708         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8709         rsurface.modelelement3i = model->surfmesh.data_element3i;
8710         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8711         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8712         rsurface.modelelement3s = model->surfmesh.data_element3s;
8713         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8714         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8715         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8716         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8717         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8718         rsurface.modelsurfaces = model->data_surfaces;
8719         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8720         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8721         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8722         rsurface.modelgeneratedvertex = false;
8723         rsurface.batchgeneratedvertex = false;
8724         rsurface.batchfirstvertex = 0;
8725         rsurface.batchnumvertices = 0;
8726         rsurface.batchfirsttriangle = 0;
8727         rsurface.batchnumtriangles = 0;
8728         rsurface.batchvertex3f  = NULL;
8729         rsurface.batchvertex3f_vertexbuffer = NULL;
8730         rsurface.batchvertex3f_bufferoffset = 0;
8731         rsurface.batchsvector3f = NULL;
8732         rsurface.batchsvector3f_vertexbuffer = NULL;
8733         rsurface.batchsvector3f_bufferoffset = 0;
8734         rsurface.batchtvector3f = NULL;
8735         rsurface.batchtvector3f_vertexbuffer = NULL;
8736         rsurface.batchtvector3f_bufferoffset = 0;
8737         rsurface.batchnormal3f  = NULL;
8738         rsurface.batchnormal3f_vertexbuffer = NULL;
8739         rsurface.batchnormal3f_bufferoffset = 0;
8740         rsurface.batchlightmapcolor4f = NULL;
8741         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8742         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8743         rsurface.batchtexcoordtexture2f = NULL;
8744         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8745         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8746         rsurface.batchtexcoordlightmap2f = NULL;
8747         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8748         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8749         rsurface.batchskeletalindex4ub = NULL;
8750         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8751         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8752         rsurface.batchskeletalweight4ub = NULL;
8753         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8754         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8755         rsurface.batchvertexmesh = NULL;
8756         rsurface.batchvertexmesh_vertexbuffer = NULL;
8757         rsurface.batchvertexmesh_bufferoffset = 0;
8758         rsurface.batchelement3i = NULL;
8759         rsurface.batchelement3i_indexbuffer = NULL;
8760         rsurface.batchelement3i_bufferoffset = 0;
8761         rsurface.batchelement3s = NULL;
8762         rsurface.batchelement3s_indexbuffer = NULL;
8763         rsurface.batchelement3s_bufferoffset = 0;
8764         rsurface.passcolor4f = NULL;
8765         rsurface.passcolor4f_vertexbuffer = NULL;
8766         rsurface.passcolor4f_bufferoffset = 0;
8767         rsurface.forcecurrenttextureupdate = false;
8768 }
8769
8770 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8771 {
8772         dp_model_t *model = ent->model;
8773         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8774         //      return;
8775         rsurface.entity = (entity_render_t *)ent;
8776         rsurface.skeleton = ent->skeleton;
8777         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8778         rsurface.ent_skinnum = ent->skinnum;
8779         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;
8780         rsurface.ent_flags = ent->flags;
8781         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8782         {
8783                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8784         }
8785         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8786         rsurface.matrix = ent->matrix;
8787         rsurface.inversematrix = ent->inversematrix;
8788         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8789         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8790         R_EntityMatrix(&rsurface.matrix);
8791         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8792         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8793         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8794         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8795         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8796         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8797         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8798         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8799         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8800         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8801         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8802         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8803         rsurface.colormod[3] = ent->alpha;
8804         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8805         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8806         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8807         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8808         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8809         if (ent->model->brush.submodel && !prepass)
8810         {
8811                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8812                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8813         }
8814         // if the animcache code decided it should use the shader path, skip the deform step
8815         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8816         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8817         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8818         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8819         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8820         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8821         {
8822                 if (ent->animcache_vertex3f)
8823                 {
8824                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8825                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8826                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8827                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8828                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8829                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8830                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8831                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8832                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8833                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8834                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8835                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8836                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8837                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8838                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8839                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8840                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8841                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8842                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8843                 }
8844                 else if (wanttangents)
8845                 {
8846                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8847                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8848                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8849                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8850                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8851                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8852                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8853                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8854                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8855                         rsurface.modelvertexmesh = NULL;
8856                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8857                         rsurface.modelvertexmesh_bufferoffset = 0;
8858                         rsurface.modelvertex3f_vertexbuffer = NULL;
8859                         rsurface.modelvertex3f_bufferoffset = 0;
8860                         rsurface.modelvertex3f_vertexbuffer = 0;
8861                         rsurface.modelvertex3f_bufferoffset = 0;
8862                         rsurface.modelsvector3f_vertexbuffer = 0;
8863                         rsurface.modelsvector3f_bufferoffset = 0;
8864                         rsurface.modeltvector3f_vertexbuffer = 0;
8865                         rsurface.modeltvector3f_bufferoffset = 0;
8866                         rsurface.modelnormal3f_vertexbuffer = 0;
8867                         rsurface.modelnormal3f_bufferoffset = 0;
8868                 }
8869                 else if (wantnormals)
8870                 {
8871                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8872                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8873                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8874                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8875                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8876                         rsurface.modelsvector3f = NULL;
8877                         rsurface.modeltvector3f = NULL;
8878                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8879                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8880                         rsurface.modelvertexmesh = NULL;
8881                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8882                         rsurface.modelvertexmesh_bufferoffset = 0;
8883                         rsurface.modelvertex3f_vertexbuffer = NULL;
8884                         rsurface.modelvertex3f_bufferoffset = 0;
8885                         rsurface.modelvertex3f_vertexbuffer = 0;
8886                         rsurface.modelvertex3f_bufferoffset = 0;
8887                         rsurface.modelsvector3f_vertexbuffer = 0;
8888                         rsurface.modelsvector3f_bufferoffset = 0;
8889                         rsurface.modeltvector3f_vertexbuffer = 0;
8890                         rsurface.modeltvector3f_bufferoffset = 0;
8891                         rsurface.modelnormal3f_vertexbuffer = 0;
8892                         rsurface.modelnormal3f_bufferoffset = 0;
8893                 }
8894                 else
8895                 {
8896                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8897                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8898                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8899                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8900                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8901                         rsurface.modelsvector3f = NULL;
8902                         rsurface.modeltvector3f = NULL;
8903                         rsurface.modelnormal3f = NULL;
8904                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8905                         rsurface.modelvertexmesh = NULL;
8906                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8907                         rsurface.modelvertexmesh_bufferoffset = 0;
8908                         rsurface.modelvertex3f_vertexbuffer = NULL;
8909                         rsurface.modelvertex3f_bufferoffset = 0;
8910                         rsurface.modelvertex3f_vertexbuffer = 0;
8911                         rsurface.modelvertex3f_bufferoffset = 0;
8912                         rsurface.modelsvector3f_vertexbuffer = 0;
8913                         rsurface.modelsvector3f_bufferoffset = 0;
8914                         rsurface.modeltvector3f_vertexbuffer = 0;
8915                         rsurface.modeltvector3f_bufferoffset = 0;
8916                         rsurface.modelnormal3f_vertexbuffer = 0;
8917                         rsurface.modelnormal3f_bufferoffset = 0;
8918                 }
8919                 rsurface.modelgeneratedvertex = true;
8920         }
8921         else
8922         {
8923                 if (rsurface.entityskeletaltransform3x4)
8924                 {
8925                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8926                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8927                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8928                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8929                 }
8930                 else
8931                 {
8932                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8933                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8934                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8935                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8936                 }
8937                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8938                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8939                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8940                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8941                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8942                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8943                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8944                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8945                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8946                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8947                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8948                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8949                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8950                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8951                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8952                 rsurface.modelgeneratedvertex = false;
8953         }
8954         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8955         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8956         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8957         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8958         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8959         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8960         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8961         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8962         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8963         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8964         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8965         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8966         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8967         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8968         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8969         rsurface.modelelement3i = model->surfmesh.data_element3i;
8970         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8971         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8972         rsurface.modelelement3s = model->surfmesh.data_element3s;
8973         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8974         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8975         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8976         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8977         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8978         rsurface.modelsurfaces = model->data_surfaces;
8979         rsurface.batchgeneratedvertex = false;
8980         rsurface.batchfirstvertex = 0;
8981         rsurface.batchnumvertices = 0;
8982         rsurface.batchfirsttriangle = 0;
8983         rsurface.batchnumtriangles = 0;
8984         rsurface.batchvertex3f  = NULL;
8985         rsurface.batchvertex3f_vertexbuffer = NULL;
8986         rsurface.batchvertex3f_bufferoffset = 0;
8987         rsurface.batchsvector3f = NULL;
8988         rsurface.batchsvector3f_vertexbuffer = NULL;
8989         rsurface.batchsvector3f_bufferoffset = 0;
8990         rsurface.batchtvector3f = NULL;
8991         rsurface.batchtvector3f_vertexbuffer = NULL;
8992         rsurface.batchtvector3f_bufferoffset = 0;
8993         rsurface.batchnormal3f  = NULL;
8994         rsurface.batchnormal3f_vertexbuffer = NULL;
8995         rsurface.batchnormal3f_bufferoffset = 0;
8996         rsurface.batchlightmapcolor4f = NULL;
8997         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8998         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8999         rsurface.batchtexcoordtexture2f = NULL;
9000         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9001         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9002         rsurface.batchtexcoordlightmap2f = NULL;
9003         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9004         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9005         rsurface.batchskeletalindex4ub = NULL;
9006         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9007         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9008         rsurface.batchskeletalweight4ub = NULL;
9009         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9010         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9011         rsurface.batchvertexmesh = NULL;
9012         rsurface.batchvertexmesh_vertexbuffer = NULL;
9013         rsurface.batchvertexmesh_bufferoffset = 0;
9014         rsurface.batchelement3i = NULL;
9015         rsurface.batchelement3i_indexbuffer = NULL;
9016         rsurface.batchelement3i_bufferoffset = 0;
9017         rsurface.batchelement3s = NULL;
9018         rsurface.batchelement3s_indexbuffer = NULL;
9019         rsurface.batchelement3s_bufferoffset = 0;
9020         rsurface.passcolor4f = NULL;
9021         rsurface.passcolor4f_vertexbuffer = NULL;
9022         rsurface.passcolor4f_bufferoffset = 0;
9023         rsurface.forcecurrenttextureupdate = false;
9024 }
9025
9026 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)
9027 {
9028         rsurface.entity = r_refdef.scene.worldentity;
9029         rsurface.skeleton = NULL;
9030         rsurface.ent_skinnum = 0;
9031         rsurface.ent_qwskin = -1;
9032         rsurface.ent_flags = entflags;
9033         rsurface.shadertime = r_refdef.scene.time - shadertime;
9034         rsurface.modelnumvertices = numvertices;
9035         rsurface.modelnumtriangles = numtriangles;
9036         rsurface.matrix = *matrix;
9037         rsurface.inversematrix = *inversematrix;
9038         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9039         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9040         R_EntityMatrix(&rsurface.matrix);
9041         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9042         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9043         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9044         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9045         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9046         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9047         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9048         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9049         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9050         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9051         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9052         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9053         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
9054         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9055         rsurface.frameblend[0].lerp = 1;
9056         rsurface.ent_alttextures = false;
9057         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9058         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9059         rsurface.entityskeletaltransform3x4 = NULL;
9060         rsurface.entityskeletaltransform3x4buffer = NULL;
9061         rsurface.entityskeletaltransform3x4offset = 0;
9062         rsurface.entityskeletaltransform3x4size = 0;
9063         rsurface.entityskeletalnumtransforms = 0;
9064         r_refdef.stats[r_stat_batch_entitycustom_count]++;
9065         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9066         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9067         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9068         if (wanttangents)
9069         {
9070                 rsurface.modelvertex3f = (float *)vertex3f;
9071                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9072                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9073                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9074         }
9075         else if (wantnormals)
9076         {
9077                 rsurface.modelvertex3f = (float *)vertex3f;
9078                 rsurface.modelsvector3f = NULL;
9079                 rsurface.modeltvector3f = NULL;
9080                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9081         }
9082         else
9083         {
9084                 rsurface.modelvertex3f = (float *)vertex3f;
9085                 rsurface.modelsvector3f = NULL;
9086                 rsurface.modeltvector3f = NULL;
9087                 rsurface.modelnormal3f = NULL;
9088         }
9089         rsurface.modelvertexmesh = NULL;
9090         rsurface.modelvertexmesh_vertexbuffer = NULL;
9091         rsurface.modelvertexmesh_bufferoffset = 0;
9092         rsurface.modelvertex3f_vertexbuffer = 0;
9093         rsurface.modelvertex3f_bufferoffset = 0;
9094         rsurface.modelsvector3f_vertexbuffer = 0;
9095         rsurface.modelsvector3f_bufferoffset = 0;
9096         rsurface.modeltvector3f_vertexbuffer = 0;
9097         rsurface.modeltvector3f_bufferoffset = 0;
9098         rsurface.modelnormal3f_vertexbuffer = 0;
9099         rsurface.modelnormal3f_bufferoffset = 0;
9100         rsurface.modelgeneratedvertex = true;
9101         rsurface.modellightmapcolor4f  = (float *)color4f;
9102         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9103         rsurface.modellightmapcolor4f_bufferoffset = 0;
9104         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9105         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9106         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9107         rsurface.modeltexcoordlightmap2f  = NULL;
9108         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9109         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9110         rsurface.modelskeletalindex4ub = NULL;
9111         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9112         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9113         rsurface.modelskeletalweight4ub = NULL;
9114         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9115         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9116         rsurface.modelelement3i = (int *)element3i;
9117         rsurface.modelelement3i_indexbuffer = NULL;
9118         rsurface.modelelement3i_bufferoffset = 0;
9119         rsurface.modelelement3s = (unsigned short *)element3s;
9120         rsurface.modelelement3s_indexbuffer = NULL;
9121         rsurface.modelelement3s_bufferoffset = 0;
9122         rsurface.modellightmapoffsets = NULL;
9123         rsurface.modelsurfaces = NULL;
9124         rsurface.batchgeneratedvertex = false;
9125         rsurface.batchfirstvertex = 0;
9126         rsurface.batchnumvertices = 0;
9127         rsurface.batchfirsttriangle = 0;
9128         rsurface.batchnumtriangles = 0;
9129         rsurface.batchvertex3f  = NULL;
9130         rsurface.batchvertex3f_vertexbuffer = NULL;
9131         rsurface.batchvertex3f_bufferoffset = 0;
9132         rsurface.batchsvector3f = NULL;
9133         rsurface.batchsvector3f_vertexbuffer = NULL;
9134         rsurface.batchsvector3f_bufferoffset = 0;
9135         rsurface.batchtvector3f = NULL;
9136         rsurface.batchtvector3f_vertexbuffer = NULL;
9137         rsurface.batchtvector3f_bufferoffset = 0;
9138         rsurface.batchnormal3f  = NULL;
9139         rsurface.batchnormal3f_vertexbuffer = NULL;
9140         rsurface.batchnormal3f_bufferoffset = 0;
9141         rsurface.batchlightmapcolor4f = NULL;
9142         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9143         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9144         rsurface.batchtexcoordtexture2f = NULL;
9145         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9146         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9147         rsurface.batchtexcoordlightmap2f = NULL;
9148         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9149         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9150         rsurface.batchskeletalindex4ub = NULL;
9151         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9152         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9153         rsurface.batchskeletalweight4ub = NULL;
9154         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9155         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9156         rsurface.batchvertexmesh = NULL;
9157         rsurface.batchvertexmesh_vertexbuffer = NULL;
9158         rsurface.batchvertexmesh_bufferoffset = 0;
9159         rsurface.batchelement3i = NULL;
9160         rsurface.batchelement3i_indexbuffer = NULL;
9161         rsurface.batchelement3i_bufferoffset = 0;
9162         rsurface.batchelement3s = NULL;
9163         rsurface.batchelement3s_indexbuffer = NULL;
9164         rsurface.batchelement3s_bufferoffset = 0;
9165         rsurface.passcolor4f = NULL;
9166         rsurface.passcolor4f_vertexbuffer = NULL;
9167         rsurface.passcolor4f_bufferoffset = 0;
9168         rsurface.forcecurrenttextureupdate = true;
9169
9170         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9171         {
9172                 if ((wantnormals || wanttangents) && !normal3f)
9173                 {
9174                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9175                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9176                 }
9177                 if (wanttangents && !svector3f)
9178                 {
9179                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9180                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9181                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9182                 }
9183         }
9184 }
9185
9186 float RSurf_FogPoint(const float *v)
9187 {
9188         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9189         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9190         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9191         float FogHeightFade = r_refdef.fogheightfade;
9192         float fogfrac;
9193         unsigned int fogmasktableindex;
9194         if (r_refdef.fogplaneviewabove)
9195                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9196         else
9197                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9198         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9199         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9200 }
9201
9202 float RSurf_FogVertex(const float *v)
9203 {
9204         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9205         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9206         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9207         float FogHeightFade = rsurface.fogheightfade;
9208         float fogfrac;
9209         unsigned int fogmasktableindex;
9210         if (r_refdef.fogplaneviewabove)
9211                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9212         else
9213                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9214         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9215         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9216 }
9217
9218 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9219 {
9220         int i;
9221         for (i = 0;i < numelements;i++)
9222                 outelement3i[i] = inelement3i[i] + adjust;
9223 }
9224
9225 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9226 extern cvar_t gl_vbo;
9227 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9228 {
9229         int deformindex;
9230         int firsttriangle;
9231         int numtriangles;
9232         int firstvertex;
9233         int endvertex;
9234         int numvertices;
9235         int surfacefirsttriangle;
9236         int surfacenumtriangles;
9237         int surfacefirstvertex;
9238         int surfaceendvertex;
9239         int surfacenumvertices;
9240         int batchnumsurfaces = texturenumsurfaces;
9241         int batchnumvertices;
9242         int batchnumtriangles;
9243         int needsupdate;
9244         int i, j;
9245         qboolean gaps;
9246         qboolean dynamicvertex;
9247         float amplitude;
9248         float animpos;
9249         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9250         float waveparms[4];
9251         unsigned char *ub;
9252         q3shaderinfo_deform_t *deform;
9253         const msurface_t *surface, *firstsurface;
9254         r_vertexmesh_t *vertexmesh;
9255         if (!texturenumsurfaces)
9256                 return;
9257         // find vertex range of this surface batch
9258         gaps = false;
9259         firstsurface = texturesurfacelist[0];
9260         firsttriangle = firstsurface->num_firsttriangle;
9261         batchnumvertices = 0;
9262         batchnumtriangles = 0;
9263         firstvertex = endvertex = firstsurface->num_firstvertex;
9264         for (i = 0;i < texturenumsurfaces;i++)
9265         {
9266                 surface = texturesurfacelist[i];
9267                 if (surface != firstsurface + i)
9268                         gaps = true;
9269                 surfacefirstvertex = surface->num_firstvertex;
9270                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9271                 surfacenumvertices = surface->num_vertices;
9272                 surfacenumtriangles = surface->num_triangles;
9273                 if (firstvertex > surfacefirstvertex)
9274                         firstvertex = surfacefirstvertex;
9275                 if (endvertex < surfaceendvertex)
9276                         endvertex = surfaceendvertex;
9277                 batchnumvertices += surfacenumvertices;
9278                 batchnumtriangles += surfacenumtriangles;
9279         }
9280
9281         r_refdef.stats[r_stat_batch_batches]++;
9282         if (gaps)
9283                 r_refdef.stats[r_stat_batch_withgaps]++;
9284         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9285         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9286         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9287
9288         // we now know the vertex range used, and if there are any gaps in it
9289         rsurface.batchfirstvertex = firstvertex;
9290         rsurface.batchnumvertices = endvertex - firstvertex;
9291         rsurface.batchfirsttriangle = firsttriangle;
9292         rsurface.batchnumtriangles = batchnumtriangles;
9293
9294         // this variable holds flags for which properties have been updated that
9295         // may require regenerating vertexmesh array...
9296         needsupdate = 0;
9297
9298         // check if any dynamic vertex processing must occur
9299         dynamicvertex = false;
9300
9301         // a cvar to force the dynamic vertex path to be taken, for debugging
9302         if (r_batch_debugdynamicvertexpath.integer)
9303         {
9304                 if (!dynamicvertex)
9305                 {
9306                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9307                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9308                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9309                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9310                 }
9311                 dynamicvertex = true;
9312         }
9313
9314         // if there is a chance of animated vertex colors, it's a dynamic batch
9315         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9316         {
9317                 if (!dynamicvertex)
9318                 {
9319                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9320                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9321                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9322                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9323                 }
9324                 dynamicvertex = true;
9325                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9326         }
9327
9328         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9329         {
9330                 switch (deform->deform)
9331                 {
9332                 default:
9333                 case Q3DEFORM_PROJECTIONSHADOW:
9334                 case Q3DEFORM_TEXT0:
9335                 case Q3DEFORM_TEXT1:
9336                 case Q3DEFORM_TEXT2:
9337                 case Q3DEFORM_TEXT3:
9338                 case Q3DEFORM_TEXT4:
9339                 case Q3DEFORM_TEXT5:
9340                 case Q3DEFORM_TEXT6:
9341                 case Q3DEFORM_TEXT7:
9342                 case Q3DEFORM_NONE:
9343                         break;
9344                 case Q3DEFORM_AUTOSPRITE:
9345                         if (!dynamicvertex)
9346                         {
9347                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9348                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9349                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9350                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9351                         }
9352                         dynamicvertex = true;
9353                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9354                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9355                         break;
9356                 case Q3DEFORM_AUTOSPRITE2:
9357                         if (!dynamicvertex)
9358                         {
9359                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9360                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9361                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9362                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9363                         }
9364                         dynamicvertex = true;
9365                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9366                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9367                         break;
9368                 case Q3DEFORM_NORMAL:
9369                         if (!dynamicvertex)
9370                         {
9371                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9372                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9373                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9374                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9375                         }
9376                         dynamicvertex = true;
9377                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9378                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9379                         break;
9380                 case Q3DEFORM_WAVE:
9381                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9382                                 break; // if wavefunc is a nop, ignore this transform
9383                         if (!dynamicvertex)
9384                         {
9385                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9386                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9387                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9388                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9389                         }
9390                         dynamicvertex = true;
9391                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9392                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9393                         break;
9394                 case Q3DEFORM_BULGE:
9395                         if (!dynamicvertex)
9396                         {
9397                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9398                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9399                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9400                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9401                         }
9402                         dynamicvertex = true;
9403                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9404                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9405                         break;
9406                 case Q3DEFORM_MOVE:
9407                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9408                                 break; // if wavefunc is a nop, ignore this transform
9409                         if (!dynamicvertex)
9410                         {
9411                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9412                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9413                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9414                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9415                         }
9416                         dynamicvertex = true;
9417                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9418                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9419                         break;
9420                 }
9421         }
9422         if (rsurface.texture->materialshaderpass)
9423         {
9424                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9425                 {
9426                 default:
9427                 case Q3TCGEN_TEXTURE:
9428                         break;
9429                 case Q3TCGEN_LIGHTMAP:
9430                         if (!dynamicvertex)
9431                         {
9432                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9433                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9434                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9435                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9436                         }
9437                         dynamicvertex = true;
9438                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9439                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9440                         break;
9441                 case Q3TCGEN_VECTOR:
9442                         if (!dynamicvertex)
9443                         {
9444                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9445                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9446                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9447                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9448                         }
9449                         dynamicvertex = true;
9450                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9451                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9452                         break;
9453                 case Q3TCGEN_ENVIRONMENT:
9454                         if (!dynamicvertex)
9455                         {
9456                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9457                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9458                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9459                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9460                         }
9461                         dynamicvertex = true;
9462                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9463                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9464                         break;
9465                 }
9466                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9467                 {
9468                         if (!dynamicvertex)
9469                         {
9470                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9471                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9472                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9473                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9474                         }
9475                         dynamicvertex = true;
9476                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9477                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9478                 }
9479         }
9480
9481         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9482         {
9483                 if (!dynamicvertex)
9484                 {
9485                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9486                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9487                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9488                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9489                 }
9490                 dynamicvertex = true;
9491                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9492         }
9493
9494         // when the model data has no vertex buffer (dynamic mesh), we need to
9495         // eliminate gaps
9496         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9497                 batchneed |= BATCHNEED_NOGAPS;
9498
9499         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9500         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9501         // we ensure this by treating the vertex batch as dynamic...
9502         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9503         {
9504                 if (!dynamicvertex)
9505                 {
9506                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9507                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9508                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9509                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9510                 }
9511                 dynamicvertex = true;
9512         }
9513
9514         if (dynamicvertex)
9515         {
9516                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9517                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9518                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9519                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9520                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9521                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9522                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9523                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9524         }
9525
9526         // if needsupdate, we have to do a dynamic vertex batch for sure
9527         if (needsupdate & batchneed)
9528         {
9529                 if (!dynamicvertex)
9530                 {
9531                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9532                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9533                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9534                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9535                 }
9536                 dynamicvertex = true;
9537         }
9538
9539         // see if we need to build vertexmesh from arrays
9540         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9541         {
9542                 if (!dynamicvertex)
9543                 {
9544                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9545                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9546                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9547                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9548                 }
9549                 dynamicvertex = true;
9550         }
9551
9552         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9553         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9554                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9555
9556         rsurface.batchvertex3f = rsurface.modelvertex3f;
9557         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9558         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9559         rsurface.batchsvector3f = rsurface.modelsvector3f;
9560         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9561         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9562         rsurface.batchtvector3f = rsurface.modeltvector3f;
9563         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9564         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9565         rsurface.batchnormal3f = rsurface.modelnormal3f;
9566         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9567         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9568         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9569         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9570         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9571         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9572         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9573         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9574         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9575         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9576         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9577         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9578         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9579         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9580         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9581         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9582         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9583         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9584         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9585         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9586         rsurface.batchelement3i = rsurface.modelelement3i;
9587         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9588         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9589         rsurface.batchelement3s = rsurface.modelelement3s;
9590         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9591         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9592         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9593         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9594         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9595         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9596         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9597
9598         // if any dynamic vertex processing has to occur in software, we copy the
9599         // entire surface list together before processing to rebase the vertices
9600         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9601         //
9602         // if any gaps exist and we do not have a static vertex buffer, we have to
9603         // copy the surface list together to avoid wasting upload bandwidth on the
9604         // vertices in the gaps.
9605         //
9606         // if gaps exist and we have a static vertex buffer, we can choose whether
9607         // to combine the index buffer ranges into one dynamic index buffer or
9608         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9609         //
9610         // in many cases the batch is reduced to one draw call.
9611
9612         rsurface.batchmultidraw = false;
9613         rsurface.batchmultidrawnumsurfaces = 0;
9614         rsurface.batchmultidrawsurfacelist = NULL;
9615
9616         if (!dynamicvertex)
9617         {
9618                 // static vertex data, just set pointers...
9619                 rsurface.batchgeneratedvertex = false;
9620                 // if there are gaps, we want to build a combined index buffer,
9621                 // otherwise use the original static buffer with an appropriate offset
9622                 if (gaps)
9623                 {
9624                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9625                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9626                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9627                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9628                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9629                         {
9630                                 rsurface.batchmultidraw = true;
9631                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9632                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9633                                 return;
9634                         }
9635                         // build a new triangle elements array for this batch
9636                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9637                         rsurface.batchfirsttriangle = 0;
9638                         numtriangles = 0;
9639                         for (i = 0;i < texturenumsurfaces;i++)
9640                         {
9641                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9642                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9643                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9644                                 numtriangles += surfacenumtriangles;
9645                         }
9646                         rsurface.batchelement3i_indexbuffer = NULL;
9647                         rsurface.batchelement3i_bufferoffset = 0;
9648                         rsurface.batchelement3s = NULL;
9649                         rsurface.batchelement3s_indexbuffer = NULL;
9650                         rsurface.batchelement3s_bufferoffset = 0;
9651                         if (endvertex <= 65536)
9652                         {
9653                                 // make a 16bit (unsigned short) index array if possible
9654                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9655                                 for (i = 0;i < numtriangles*3;i++)
9656                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9657                         }
9658                         // upload buffer data for the copytriangles batch
9659                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9660                         {
9661                                 if (rsurface.batchelement3s)
9662                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9663                                 else if (rsurface.batchelement3i)
9664                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9665                         }
9666                 }
9667                 else
9668                 {
9669                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9670                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9671                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9672                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9673                 }
9674                 return;
9675         }
9676
9677         // something needs software processing, do it for real...
9678         // we only directly handle separate array data in this case and then
9679         // generate interleaved data if needed...
9680         rsurface.batchgeneratedvertex = true;
9681         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9682         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9683         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9684         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9685
9686         // now copy the vertex data into a combined array and make an index array
9687         // (this is what Quake3 does all the time)
9688         // we also apply any skeletal animation here that would have been done in
9689         // the vertex shader, because most of the dynamic vertex animation cases
9690         // need actual vertex positions and normals
9691         //if (dynamicvertex)
9692         {
9693                 rsurface.batchvertexmesh = NULL;
9694                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9695                 rsurface.batchvertexmesh_bufferoffset = 0;
9696                 rsurface.batchvertex3f = NULL;
9697                 rsurface.batchvertex3f_vertexbuffer = NULL;
9698                 rsurface.batchvertex3f_bufferoffset = 0;
9699                 rsurface.batchsvector3f = NULL;
9700                 rsurface.batchsvector3f_vertexbuffer = NULL;
9701                 rsurface.batchsvector3f_bufferoffset = 0;
9702                 rsurface.batchtvector3f = NULL;
9703                 rsurface.batchtvector3f_vertexbuffer = NULL;
9704                 rsurface.batchtvector3f_bufferoffset = 0;
9705                 rsurface.batchnormal3f = NULL;
9706                 rsurface.batchnormal3f_vertexbuffer = NULL;
9707                 rsurface.batchnormal3f_bufferoffset = 0;
9708                 rsurface.batchlightmapcolor4f = NULL;
9709                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9710                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9711                 rsurface.batchtexcoordtexture2f = NULL;
9712                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9713                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9714                 rsurface.batchtexcoordlightmap2f = NULL;
9715                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9716                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9717                 rsurface.batchskeletalindex4ub = NULL;
9718                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9719                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9720                 rsurface.batchskeletalweight4ub = NULL;
9721                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9722                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9723                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9724                 rsurface.batchelement3i_indexbuffer = NULL;
9725                 rsurface.batchelement3i_bufferoffset = 0;
9726                 rsurface.batchelement3s = NULL;
9727                 rsurface.batchelement3s_indexbuffer = NULL;
9728                 rsurface.batchelement3s_bufferoffset = 0;
9729                 rsurface.batchskeletaltransform3x4buffer = NULL;
9730                 rsurface.batchskeletaltransform3x4offset = 0;
9731                 rsurface.batchskeletaltransform3x4size = 0;
9732                 // we'll only be setting up certain arrays as needed
9733                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9734                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9735                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9736                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9737                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9738                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9739                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9740                 {
9741                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9742                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9743                 }
9744                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9745                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9746                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9747                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9748                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9749                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9750                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9751                 {
9752                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9753                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9754                 }
9755                 numvertices = 0;
9756                 numtriangles = 0;
9757                 for (i = 0;i < texturenumsurfaces;i++)
9758                 {
9759                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9760                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9761                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9762                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9763                         // copy only the data requested
9764                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9765                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9766                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9767                         {
9768                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9769                                 {
9770                                         if (rsurface.batchvertex3f)
9771                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9772                                         else
9773                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9774                                 }
9775                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9776                                 {
9777                                         if (rsurface.modelnormal3f)
9778                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9779                                         else
9780                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9781                                 }
9782                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9783                                 {
9784                                         if (rsurface.modelsvector3f)
9785                                         {
9786                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9787                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9788                                         }
9789                                         else
9790                                         {
9791                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9792                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9793                                         }
9794                                 }
9795                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9796                                 {
9797                                         if (rsurface.modellightmapcolor4f)
9798                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9799                                         else
9800                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9801                                 }
9802                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9803                                 {
9804                                         if (rsurface.modeltexcoordtexture2f)
9805                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9806                                         else
9807                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9808                                 }
9809                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9810                                 {
9811                                         if (rsurface.modeltexcoordlightmap2f)
9812                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9813                                         else
9814                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9815                                 }
9816                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9817                                 {
9818                                         if (rsurface.modelskeletalindex4ub)
9819                                         {
9820                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9821                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9822                                         }
9823                                         else
9824                                         {
9825                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9826                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9827                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9828                                                 for (j = 0;j < surfacenumvertices;j++)
9829                                                         ub[j*4] = 255;
9830                                         }
9831                                 }
9832                         }
9833                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9834                         numvertices += surfacenumvertices;
9835                         numtriangles += surfacenumtriangles;
9836                 }
9837
9838                 // generate a 16bit index array as well if possible
9839                 // (in general, dynamic batches fit)
9840                 if (numvertices <= 65536)
9841                 {
9842                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9843                         for (i = 0;i < numtriangles*3;i++)
9844                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9845                 }
9846
9847                 // since we've copied everything, the batch now starts at 0
9848                 rsurface.batchfirstvertex = 0;
9849                 rsurface.batchnumvertices = batchnumvertices;
9850                 rsurface.batchfirsttriangle = 0;
9851                 rsurface.batchnumtriangles = batchnumtriangles;
9852         }
9853
9854         // apply skeletal animation that would have been done in the vertex shader
9855         if (rsurface.batchskeletaltransform3x4)
9856         {
9857                 const unsigned char *si;
9858                 const unsigned char *sw;
9859                 const float *t[4];
9860                 const float *b = rsurface.batchskeletaltransform3x4;
9861                 float *vp, *vs, *vt, *vn;
9862                 float w[4];
9863                 float m[3][4], n[3][4];
9864                 float tp[3], ts[3], tt[3], tn[3];
9865                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9866                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9867                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9868                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9869                 si = rsurface.batchskeletalindex4ub;
9870                 sw = rsurface.batchskeletalweight4ub;
9871                 vp = rsurface.batchvertex3f;
9872                 vs = rsurface.batchsvector3f;
9873                 vt = rsurface.batchtvector3f;
9874                 vn = rsurface.batchnormal3f;
9875                 memset(m[0], 0, sizeof(m));
9876                 memset(n[0], 0, sizeof(n));
9877                 for (i = 0;i < batchnumvertices;i++)
9878                 {
9879                         t[0] = b + si[0]*12;
9880                         if (sw[0] == 255)
9881                         {
9882                                 // common case - only one matrix
9883                                 m[0][0] = t[0][ 0];
9884                                 m[0][1] = t[0][ 1];
9885                                 m[0][2] = t[0][ 2];
9886                                 m[0][3] = t[0][ 3];
9887                                 m[1][0] = t[0][ 4];
9888                                 m[1][1] = t[0][ 5];
9889                                 m[1][2] = t[0][ 6];
9890                                 m[1][3] = t[0][ 7];
9891                                 m[2][0] = t[0][ 8];
9892                                 m[2][1] = t[0][ 9];
9893                                 m[2][2] = t[0][10];
9894                                 m[2][3] = t[0][11];
9895                         }
9896                         else if (sw[2] + sw[3])
9897                         {
9898                                 // blend 4 matrices
9899                                 t[1] = b + si[1]*12;
9900                                 t[2] = b + si[2]*12;
9901                                 t[3] = b + si[3]*12;
9902                                 w[0] = sw[0] * (1.0f / 255.0f);
9903                                 w[1] = sw[1] * (1.0f / 255.0f);
9904                                 w[2] = sw[2] * (1.0f / 255.0f);
9905                                 w[3] = sw[3] * (1.0f / 255.0f);
9906                                 // blend the matrices
9907                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9908                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9909                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9910                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9911                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9912                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9913                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9914                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9915                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9916                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9917                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9918                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9919                         }
9920                         else
9921                         {
9922                                 // blend 2 matrices
9923                                 t[1] = b + si[1]*12;
9924                                 w[0] = sw[0] * (1.0f / 255.0f);
9925                                 w[1] = sw[1] * (1.0f / 255.0f);
9926                                 // blend the matrices
9927                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9928                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9929                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9930                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9931                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9932                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9933                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9934                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9935                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9936                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9937                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9938                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9939                         }
9940                         si += 4;
9941                         sw += 4;
9942                         // modify the vertex
9943                         VectorCopy(vp, tp);
9944                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9945                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9946                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9947                         vp += 3;
9948                         if (vn)
9949                         {
9950                                 // the normal transformation matrix is a set of cross products...
9951                                 CrossProduct(m[1], m[2], n[0]);
9952                                 CrossProduct(m[2], m[0], n[1]);
9953                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9954                                 VectorCopy(vn, tn);
9955                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9956                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9957                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9958                                 VectorNormalize(vn);
9959                                 vn += 3;
9960                                 if (vs)
9961                                 {
9962                                         VectorCopy(vs, ts);
9963                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9964                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9965                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9966                                         VectorNormalize(vs);
9967                                         vs += 3;
9968                                         VectorCopy(vt, tt);
9969                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9970                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9971                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9972                                         VectorNormalize(vt);
9973                                         vt += 3;
9974                                 }
9975                         }
9976                 }
9977                 rsurface.batchskeletaltransform3x4 = NULL;
9978                 rsurface.batchskeletalnumtransforms = 0;
9979         }
9980
9981         // q1bsp surfaces rendered in vertex color mode have to have colors
9982         // calculated based on lightstyles
9983         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9984         {
9985                 // generate color arrays for the surfaces in this list
9986                 int c[4];
9987                 int scale;
9988                 int size3;
9989                 const int *offsets;
9990                 const unsigned char *lm;
9991                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9992                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9993                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9994                 numvertices = 0;
9995                 for (i = 0;i < texturenumsurfaces;i++)
9996                 {
9997                         surface = texturesurfacelist[i];
9998                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9999                         surfacenumvertices = surface->num_vertices;
10000                         if (surface->lightmapinfo->samples)
10001                         {
10002                                 for (j = 0;j < surfacenumvertices;j++)
10003                                 {
10004                                         lm = surface->lightmapinfo->samples + offsets[j];
10005                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10006                                         VectorScale(lm, scale, c);
10007                                         if (surface->lightmapinfo->styles[1] != 255)
10008                                         {
10009                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10010                                                 lm += size3;
10011                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10012                                                 VectorMA(c, scale, lm, c);
10013                                                 if (surface->lightmapinfo->styles[2] != 255)
10014                                                 {
10015                                                         lm += size3;
10016                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10017                                                         VectorMA(c, scale, lm, c);
10018                                                         if (surface->lightmapinfo->styles[3] != 255)
10019                                                         {
10020                                                                 lm += size3;
10021                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10022                                                                 VectorMA(c, scale, lm, c);
10023                                                         }
10024                                                 }
10025                                         }
10026                                         c[0] >>= 7;
10027                                         c[1] >>= 7;
10028                                         c[2] >>= 7;
10029                                         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);
10030                                         numvertices++;
10031                                 }
10032                         }
10033                         else
10034                         {
10035                                 for (j = 0;j < surfacenumvertices;j++)
10036                                 {
10037                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10038                                         numvertices++;
10039                                 }
10040                         }
10041                 }
10042         }
10043
10044         // if vertices are deformed (sprite flares and things in maps, possibly
10045         // water waves, bulges and other deformations), modify the copied vertices
10046         // in place
10047         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
10048         {
10049                 float scale;
10050                 switch (deform->deform)
10051                 {
10052                 default:
10053                 case Q3DEFORM_PROJECTIONSHADOW:
10054                 case Q3DEFORM_TEXT0:
10055                 case Q3DEFORM_TEXT1:
10056                 case Q3DEFORM_TEXT2:
10057                 case Q3DEFORM_TEXT3:
10058                 case Q3DEFORM_TEXT4:
10059                 case Q3DEFORM_TEXT5:
10060                 case Q3DEFORM_TEXT6:
10061                 case Q3DEFORM_TEXT7:
10062                 case Q3DEFORM_NONE:
10063                         break;
10064                 case Q3DEFORM_AUTOSPRITE:
10065                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10066                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10067                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10068                         VectorNormalize(newforward);
10069                         VectorNormalize(newright);
10070                         VectorNormalize(newup);
10071 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10072 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10073 //                      rsurface.batchvertex3f_bufferoffset = 0;
10074 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10075 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
10076 //                      rsurface.batchsvector3f_bufferoffset = 0;
10077 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10078 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
10079 //                      rsurface.batchtvector3f_bufferoffset = 0;
10080 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10081 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10082 //                      rsurface.batchnormal3f_bufferoffset = 0;
10083                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10084                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10085                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10086                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10087                                 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);
10088                         // a single autosprite surface can contain multiple sprites...
10089                         for (j = 0;j < batchnumvertices - 3;j += 4)
10090                         {
10091                                 VectorClear(center);
10092                                 for (i = 0;i < 4;i++)
10093                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10094                                 VectorScale(center, 0.25f, center);
10095                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10096                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10097                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10098                                 for (i = 0;i < 4;i++)
10099                                 {
10100                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10101                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10102                                 }
10103                         }
10104                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10105                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10106                         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);
10107                         break;
10108                 case Q3DEFORM_AUTOSPRITE2:
10109                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10110                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10111                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10112                         VectorNormalize(newforward);
10113                         VectorNormalize(newright);
10114                         VectorNormalize(newup);
10115 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10116 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10117 //                      rsurface.batchvertex3f_bufferoffset = 0;
10118                         {
10119                                 const float *v1, *v2;
10120                                 vec3_t start, end;
10121                                 float f, l;
10122                                 struct
10123                                 {
10124                                         float length2;
10125                                         const float *v1;
10126                                         const float *v2;
10127                                 }
10128                                 shortest[2];
10129                                 memset(shortest, 0, sizeof(shortest));
10130                                 // a single autosprite surface can contain multiple sprites...
10131                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10132                                 {
10133                                         VectorClear(center);
10134                                         for (i = 0;i < 4;i++)
10135                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10136                                         VectorScale(center, 0.25f, center);
10137                                         // find the two shortest edges, then use them to define the
10138                                         // axis vectors for rotating around the central axis
10139                                         for (i = 0;i < 6;i++)
10140                                         {
10141                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10142                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10143                                                 l = VectorDistance2(v1, v2);
10144                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10145                                                 if (v1[2] != v2[2])
10146                                                         l += (1.0f / 1024.0f);
10147                                                 if (shortest[0].length2 > l || i == 0)
10148                                                 {
10149                                                         shortest[1] = shortest[0];
10150                                                         shortest[0].length2 = l;
10151                                                         shortest[0].v1 = v1;
10152                                                         shortest[0].v2 = v2;
10153                                                 }
10154                                                 else if (shortest[1].length2 > l || i == 1)
10155                                                 {
10156                                                         shortest[1].length2 = l;
10157                                                         shortest[1].v1 = v1;
10158                                                         shortest[1].v2 = v2;
10159                                                 }
10160                                         }
10161                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10162                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10163                                         // this calculates the right vector from the shortest edge
10164                                         // and the up vector from the edge midpoints
10165                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10166                                         VectorNormalize(right);
10167                                         VectorSubtract(end, start, up);
10168                                         VectorNormalize(up);
10169                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10170                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10171                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10172                                         VectorNegate(forward, forward);
10173                                         VectorReflect(forward, 0, up, forward);
10174                                         VectorNormalize(forward);
10175                                         CrossProduct(up, forward, newright);
10176                                         VectorNormalize(newright);
10177                                         // rotate the quad around the up axis vector, this is made
10178                                         // especially easy by the fact we know the quad is flat,
10179                                         // so we only have to subtract the center position and
10180                                         // measure distance along the right vector, and then
10181                                         // multiply that by the newright vector and add back the
10182                                         // center position
10183                                         // we also need to subtract the old position to undo the
10184                                         // displacement from the center, which we do with a
10185                                         // DotProduct, the subtraction/addition of center is also
10186                                         // optimized into DotProducts here
10187                                         l = DotProduct(right, center);
10188                                         for (i = 0;i < 4;i++)
10189                                         {
10190                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10191                                                 f = DotProduct(right, v1) - l;
10192                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10193                                         }
10194                                 }
10195                         }
10196                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10197                         {
10198 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10199 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10200 //                              rsurface.batchnormal3f_bufferoffset = 0;
10201                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10202                         }
10203                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10204                         {
10205 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10206 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10207 //                              rsurface.batchsvector3f_bufferoffset = 0;
10208 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10209 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10210 //                              rsurface.batchtvector3f_bufferoffset = 0;
10211                                 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);
10212                         }
10213                         break;
10214                 case Q3DEFORM_NORMAL:
10215                         // deform the normals to make reflections wavey
10216                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10217                         rsurface.batchnormal3f_vertexbuffer = NULL;
10218                         rsurface.batchnormal3f_bufferoffset = 0;
10219                         for (j = 0;j < batchnumvertices;j++)
10220                         {
10221                                 float vertex[3];
10222                                 float *normal = rsurface.batchnormal3f + 3*j;
10223                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10224                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10225                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10226                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10227                                 VectorNormalize(normal);
10228                         }
10229                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10230                         {
10231 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10232 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10233 //                              rsurface.batchsvector3f_bufferoffset = 0;
10234 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10235 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10236 //                              rsurface.batchtvector3f_bufferoffset = 0;
10237                                 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);
10238                         }
10239                         break;
10240                 case Q3DEFORM_WAVE:
10241                         // deform vertex array to make wavey water and flags and such
10242                         waveparms[0] = deform->waveparms[0];
10243                         waveparms[1] = deform->waveparms[1];
10244                         waveparms[2] = deform->waveparms[2];
10245                         waveparms[3] = deform->waveparms[3];
10246                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10247                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10248                         // this is how a divisor of vertex influence on deformation
10249                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10250                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10251 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10252 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10253 //                      rsurface.batchvertex3f_bufferoffset = 0;
10254 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10255 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10256 //                      rsurface.batchnormal3f_bufferoffset = 0;
10257                         for (j = 0;j < batchnumvertices;j++)
10258                         {
10259                                 // if the wavefunc depends on time, evaluate it per-vertex
10260                                 if (waveparms[3])
10261                                 {
10262                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10263                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10264                                 }
10265                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10266                         }
10267                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10268                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10269                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10270                         {
10271 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10272 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10273 //                              rsurface.batchsvector3f_bufferoffset = 0;
10274 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10275 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10276 //                              rsurface.batchtvector3f_bufferoffset = 0;
10277                                 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);
10278                         }
10279                         break;
10280                 case Q3DEFORM_BULGE:
10281                         // deform vertex array to make the surface have moving bulges
10282 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10283 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10284 //                      rsurface.batchvertex3f_bufferoffset = 0;
10285 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10286 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10287 //                      rsurface.batchnormal3f_bufferoffset = 0;
10288                         for (j = 0;j < batchnumvertices;j++)
10289                         {
10290                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10291                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10292                         }
10293                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10294                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10295                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10296                         {
10297 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10298 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10299 //                              rsurface.batchsvector3f_bufferoffset = 0;
10300 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10301 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10302 //                              rsurface.batchtvector3f_bufferoffset = 0;
10303                                 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);
10304                         }
10305                         break;
10306                 case Q3DEFORM_MOVE:
10307                         // deform vertex array
10308                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10309                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10310                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10311                         VectorScale(deform->parms, scale, waveparms);
10312 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10313 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10314 //                      rsurface.batchvertex3f_bufferoffset = 0;
10315                         for (j = 0;j < batchnumvertices;j++)
10316                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10317                         break;
10318                 }
10319         }
10320
10321         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10322         {
10323         // generate texcoords based on the chosen texcoord source
10324                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10325                 {
10326                 default:
10327                 case Q3TCGEN_TEXTURE:
10328                         break;
10329                 case Q3TCGEN_LIGHTMAP:
10330         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10331         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10332         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10333                         if (rsurface.batchtexcoordlightmap2f)
10334                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10335                         break;
10336                 case Q3TCGEN_VECTOR:
10337         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10338         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10339         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10340                         for (j = 0;j < batchnumvertices;j++)
10341                         {
10342                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10343                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10344                         }
10345                         break;
10346                 case Q3TCGEN_ENVIRONMENT:
10347                         // make environment reflections using a spheremap
10348                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10349                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10350                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10351                         for (j = 0;j < batchnumvertices;j++)
10352                         {
10353                                 // identical to Q3A's method, but executed in worldspace so
10354                                 // carried models can be shiny too
10355
10356                                 float viewer[3], d, reflected[3], worldreflected[3];
10357
10358                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10359                                 // VectorNormalize(viewer);
10360
10361                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10362
10363                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10364                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10365                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10366                                 // note: this is proportinal to viewer, so we can normalize later
10367
10368                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10369                                 VectorNormalize(worldreflected);
10370
10371                                 // note: this sphere map only uses world x and z!
10372                                 // so positive and negative y will LOOK THE SAME.
10373                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10374                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10375                         }
10376                         break;
10377                 }
10378                 // the only tcmod that needs software vertex processing is turbulent, so
10379                 // check for it here and apply the changes if needed
10380                 // and we only support that as the first one
10381                 // (handling a mixture of turbulent and other tcmods would be problematic
10382                 //  without punting it entirely to a software path)
10383                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10384                 {
10385                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10386                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10387         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10388         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10389         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10390                         for (j = 0;j < batchnumvertices;j++)
10391                         {
10392                                 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);
10393                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10394                         }
10395                 }
10396         }
10397
10398         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10399         {
10400                 // convert the modified arrays to vertex structs
10401 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10402 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10403 //              rsurface.batchvertexmesh_bufferoffset = 0;
10404                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10405                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10406                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10407                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10408                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10409                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10410                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10411                 {
10412                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10413                         {
10414                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10415                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10416                         }
10417                 }
10418                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10419                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10420                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10421                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10422                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10423                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10424                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10425                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10426                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10427                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10428                 {
10429                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10430                         {
10431                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10432                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10433                         }
10434                 }
10435         }
10436
10437         // upload buffer data for the dynamic batch
10438         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10439         {
10440                 if (rsurface.batchvertexmesh)
10441                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10442                 else
10443                 {
10444                         if (rsurface.batchvertex3f)
10445                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10446                         if (rsurface.batchsvector3f)
10447                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10448                         if (rsurface.batchtvector3f)
10449                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10450                         if (rsurface.batchnormal3f)
10451                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10452                         if (rsurface.batchlightmapcolor4f)
10453                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10454                         if (rsurface.batchtexcoordtexture2f)
10455                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10456                         if (rsurface.batchtexcoordlightmap2f)
10457                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10458                         if (rsurface.batchskeletalindex4ub)
10459                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10460                         if (rsurface.batchskeletalweight4ub)
10461                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10462                 }
10463                 if (rsurface.batchelement3s)
10464                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10465                 else if (rsurface.batchelement3i)
10466                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10467         }
10468 }
10469
10470 void RSurf_DrawBatch(void)
10471 {
10472         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10473         // through the pipeline, killing it earlier in the pipeline would have
10474         // per-surface overhead rather than per-batch overhead, so it's best to
10475         // reject it here, before it hits glDraw.
10476         if (rsurface.batchnumtriangles == 0)
10477                 return;
10478 #if 0
10479         // batch debugging code
10480         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10481         {
10482                 int i;
10483                 int j;
10484                 int c;
10485                 const int *e;
10486                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10487                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10488                 {
10489                         c = e[i];
10490                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10491                         {
10492                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10493                                 {
10494                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10495                                                 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);
10496                                         break;
10497                                 }
10498                         }
10499                 }
10500         }
10501 #endif
10502         if (rsurface.batchmultidraw)
10503         {
10504                 // issue multiple draws rather than copying index data
10505                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10506                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10507                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10508                 for (i = 0;i < numsurfaces;)
10509                 {
10510                         // combine consecutive surfaces as one draw
10511                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10512                                 if (surfacelist[j] != surfacelist[k] + 1)
10513                                         break;
10514                         firstvertex = surfacelist[i]->num_firstvertex;
10515                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10516                         firsttriangle = surfacelist[i]->num_firsttriangle;
10517                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10518                         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);
10519                         i = j;
10520                 }
10521         }
10522         else
10523         {
10524                 // there is only one consecutive run of index data (may have been combined)
10525                 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);
10526         }
10527 }
10528
10529 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10530 {
10531         // pick the closest matching water plane
10532         int planeindex, vertexindex, bestplaneindex = -1;
10533         float d, bestd;
10534         vec3_t vert;
10535         const float *v;
10536         r_waterstate_waterplane_t *p;
10537         qboolean prepared = false;
10538         bestd = 0;
10539         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10540         {
10541                 if(p->camera_entity != rsurface.texture->camera_entity)
10542                         continue;
10543                 d = 0;
10544                 if(!prepared)
10545                 {
10546                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10547                         prepared = true;
10548                         if(rsurface.batchnumvertices == 0)
10549                                 break;
10550                 }
10551                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10552                 {
10553                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10554                         d += fabs(PlaneDiff(vert, &p->plane));
10555                 }
10556                 if (bestd > d || bestplaneindex < 0)
10557                 {
10558                         bestd = d;
10559                         bestplaneindex = planeindex;
10560                 }
10561         }
10562         return bestplaneindex;
10563         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10564         // this situation though, as it might be better to render single larger
10565         // batches with useless stuff (backface culled for example) than to
10566         // render multiple smaller batches
10567 }
10568
10569 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10570 {
10571         int i;
10572         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10573         rsurface.passcolor4f_vertexbuffer = 0;
10574         rsurface.passcolor4f_bufferoffset = 0;
10575         for (i = 0;i < rsurface.batchnumvertices;i++)
10576                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10577 }
10578
10579 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10580 {
10581         int i;
10582         float f;
10583         const float *v;
10584         const float *c;
10585         float *c2;
10586         if (rsurface.passcolor4f)
10587         {
10588                 // generate color arrays
10589                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10590                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10591                 rsurface.passcolor4f_vertexbuffer = 0;
10592                 rsurface.passcolor4f_bufferoffset = 0;
10593                 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)
10594                 {
10595                         f = RSurf_FogVertex(v);
10596                         c2[0] = c[0] * f;
10597                         c2[1] = c[1] * f;
10598                         c2[2] = c[2] * f;
10599                         c2[3] = c[3];
10600                 }
10601         }
10602         else
10603         {
10604                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10605                 rsurface.passcolor4f_vertexbuffer = 0;
10606                 rsurface.passcolor4f_bufferoffset = 0;
10607                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10608                 {
10609                         f = RSurf_FogVertex(v);
10610                         c2[0] = f;
10611                         c2[1] = f;
10612                         c2[2] = f;
10613                         c2[3] = 1;
10614                 }
10615         }
10616 }
10617
10618 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10619 {
10620         int i;
10621         float f;
10622         const float *v;
10623         const float *c;
10624         float *c2;
10625         if (!rsurface.passcolor4f)
10626                 return;
10627         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10628         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10629         rsurface.passcolor4f_vertexbuffer = 0;
10630         rsurface.passcolor4f_bufferoffset = 0;
10631         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)
10632         {
10633                 f = RSurf_FogVertex(v);
10634                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10635                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10636                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10637                 c2[3] = c[3];
10638         }
10639 }
10640
10641 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10642 {
10643         int i;
10644         const float *c;
10645         float *c2;
10646         if (!rsurface.passcolor4f)
10647                 return;
10648         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10649         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10650         rsurface.passcolor4f_vertexbuffer = 0;
10651         rsurface.passcolor4f_bufferoffset = 0;
10652         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10653         {
10654                 c2[0] = c[0] * r;
10655                 c2[1] = c[1] * g;
10656                 c2[2] = c[2] * b;
10657                 c2[3] = c[3] * a;
10658         }
10659 }
10660
10661 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10662 {
10663         int i;
10664         const float *c;
10665         float *c2;
10666         if (!rsurface.passcolor4f)
10667                 return;
10668         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10669         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10670         rsurface.passcolor4f_vertexbuffer = 0;
10671         rsurface.passcolor4f_bufferoffset = 0;
10672         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10673         {
10674                 c2[0] = c[0] + r_refdef.scene.ambient;
10675                 c2[1] = c[1] + r_refdef.scene.ambient;
10676                 c2[2] = c[2] + r_refdef.scene.ambient;
10677                 c2[3] = c[3];
10678         }
10679 }
10680
10681 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10682 {
10683         // TODO: optimize
10684         rsurface.passcolor4f = NULL;
10685         rsurface.passcolor4f_vertexbuffer = 0;
10686         rsurface.passcolor4f_bufferoffset = 0;
10687         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10688         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10689         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10690         GL_Color(r, g, b, a);
10691         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10692         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10693         R_Mesh_TexMatrix(0, NULL);
10694         RSurf_DrawBatch();
10695 }
10696
10697 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10698 {
10699         // TODO: optimize applyfog && applycolor case
10700         // just apply fog if necessary, and tint the fog color array if necessary
10701         rsurface.passcolor4f = NULL;
10702         rsurface.passcolor4f_vertexbuffer = 0;
10703         rsurface.passcolor4f_bufferoffset = 0;
10704         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10705         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10706         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10707         GL_Color(r, g, b, a);
10708         RSurf_DrawBatch();
10709 }
10710
10711 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10712 {
10713         // TODO: optimize
10714         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10715         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10716         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10717         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10718         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10719         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10720         GL_Color(r, g, b, a);
10721         RSurf_DrawBatch();
10722 }
10723
10724 static void RSurf_DrawBatch_GL11_ClampColor(void)
10725 {
10726         int i;
10727         const float *c1;
10728         float *c2;
10729         if (!rsurface.passcolor4f)
10730                 return;
10731         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10732         {
10733                 c2[0] = bound(0.0f, c1[0], 1.0f);
10734                 c2[1] = bound(0.0f, c1[1], 1.0f);
10735                 c2[2] = bound(0.0f, c1[2], 1.0f);
10736                 c2[3] = bound(0.0f, c1[3], 1.0f);
10737         }
10738 }
10739
10740 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10741 {
10742         int i;
10743         float f;
10744         const float *v;
10745         const float *n;
10746         float *c;
10747         //vec3_t eyedir;
10748
10749         // fake shading
10750         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10751         rsurface.passcolor4f_vertexbuffer = 0;
10752         rsurface.passcolor4f_bufferoffset = 0;
10753         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)
10754         {
10755                 f = -DotProduct(r_refdef.view.forward, n);
10756                 f = max(0, f);
10757                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10758                 f *= r_refdef.lightmapintensity;
10759                 Vector4Set(c, f, f, f, 1);
10760         }
10761 }
10762
10763 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10764 {
10765         RSurf_DrawBatch_GL11_ApplyFakeLight();
10766         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10767         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10768         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10769         GL_Color(r, g, b, a);
10770         RSurf_DrawBatch();
10771 }
10772
10773 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10774 {
10775         int i;
10776         float f;
10777         float alpha;
10778         const float *v;
10779         const float *n;
10780         float *c;
10781         vec3_t ambientcolor;
10782         vec3_t diffusecolor;
10783         vec3_t lightdir;
10784         // TODO: optimize
10785         // model lighting
10786         VectorCopy(rsurface.modellight_lightdir, lightdir);
10787         f = 0.5f * r_refdef.lightmapintensity;
10788         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10789         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10790         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10791         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10792         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10793         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10794         alpha = *a;
10795         if (VectorLength2(diffusecolor) > 0)
10796         {
10797                 // q3-style directional shading
10798                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10799                 rsurface.passcolor4f_vertexbuffer = 0;
10800                 rsurface.passcolor4f_bufferoffset = 0;
10801                 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)
10802                 {
10803                         if ((f = DotProduct(n, lightdir)) > 0)
10804                                 VectorMA(ambientcolor, f, diffusecolor, c);
10805                         else
10806                                 VectorCopy(ambientcolor, c);
10807                         c[3] = alpha;
10808                 }
10809                 *r = 1;
10810                 *g = 1;
10811                 *b = 1;
10812                 *a = 1;
10813                 *applycolor = false;
10814         }
10815         else
10816         {
10817                 *r = ambientcolor[0];
10818                 *g = ambientcolor[1];
10819                 *b = ambientcolor[2];
10820                 rsurface.passcolor4f = NULL;
10821                 rsurface.passcolor4f_vertexbuffer = 0;
10822                 rsurface.passcolor4f_bufferoffset = 0;
10823         }
10824 }
10825
10826 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10827 {
10828         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10829         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10830         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10831         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10832         GL_Color(r, g, b, a);
10833         RSurf_DrawBatch();
10834 }
10835
10836 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10837 {
10838         int i;
10839         float f;
10840         const float *v;
10841         float *c;
10842
10843         // fake shading
10844         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10845         rsurface.passcolor4f_vertexbuffer = 0;
10846         rsurface.passcolor4f_bufferoffset = 0;
10847
10848         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10849         {
10850                 f = 1 - RSurf_FogVertex(v);
10851                 c[0] = r;
10852                 c[1] = g;
10853                 c[2] = b;
10854                 c[3] = f * a;
10855         }
10856 }
10857
10858 void RSurf_SetupDepthAndCulling(void)
10859 {
10860         // submodels are biased to avoid z-fighting with world surfaces that they
10861         // may be exactly overlapping (avoids z-fighting artifacts on certain
10862         // doors and things in Quake maps)
10863         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10864         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10865         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10866         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10867 }
10868
10869 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10870 {
10871         int i, j;
10872         // transparent sky would be ridiculous
10873         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10874                 return;
10875         R_SetupShader_Generic_NoTexture(false, false);
10876         skyrenderlater = true;
10877         RSurf_SetupDepthAndCulling();
10878         GL_DepthMask(true);
10879
10880         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10881         if (r_sky_scissor.integer)
10882         {
10883                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10884                 for (i = 0; i < texturenumsurfaces; i++)
10885                 {
10886                         const msurface_t *surf = texturesurfacelist[i];
10887                         const float *v;
10888                         float p[3];
10889                         float mins[3], maxs[3];
10890                         int scissor[4];
10891                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10892                         {
10893                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10894                                 if (j > 0)
10895                                 {
10896                                         if (mins[0] > p[0]) mins[0] = p[0];
10897                                         if (mins[1] > p[1]) mins[1] = p[1];
10898                                         if (mins[2] > p[2]) mins[2] = p[2];
10899                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10900                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10901                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10902                                 }
10903                                 else
10904                                 {
10905                                         VectorCopy(p, mins);
10906                                         VectorCopy(p, maxs);
10907                                 }
10908                         }
10909                         if (!R_ScissorForBBox(mins, maxs, scissor))
10910                         {
10911                                 if (skyscissor[2])
10912                                 {
10913                                         if (skyscissor[0] > scissor[0])
10914                                         {
10915                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10916                                                 skyscissor[0] = scissor[0];
10917                                         }
10918                                         if (skyscissor[1] > scissor[1])
10919                                         {
10920                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10921                                                 skyscissor[1] = scissor[1];
10922                                         }
10923                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10924                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10925                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10926                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10927                                 }
10928                                 else
10929                                         Vector4Copy(scissor, skyscissor);
10930                         }
10931                 }
10932         }
10933
10934         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10935         // skymasking on them, and Quake3 never did sky masking (unlike
10936         // software Quake and software Quake2), so disable the sky masking
10937         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10938         // and skymasking also looks very bad when noclipping outside the
10939         // level, so don't use it then either.
10940         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)
10941         {
10942                 R_Mesh_ResetTextureState();
10943                 if (skyrendermasked)
10944                 {
10945                         R_SetupShader_DepthOrShadow(false, false, false);
10946                         // depth-only (masking)
10947                         GL_ColorMask(0, 0, 0, 0);
10948                         // just to make sure that braindead drivers don't draw
10949                         // anything despite that colormask...
10950                         GL_BlendFunc(GL_ZERO, GL_ONE);
10951                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10952                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10953                 }
10954                 else
10955                 {
10956                         R_SetupShader_Generic_NoTexture(false, false);
10957                         // fog sky
10958                         GL_BlendFunc(GL_ONE, GL_ZERO);
10959                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10961                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10962                 }
10963                 RSurf_DrawBatch();
10964                 if (skyrendermasked)
10965                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10966         }
10967         R_Mesh_ResetTextureState();
10968         GL_Color(1, 1, 1, 1);
10969 }
10970
10971 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10972 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10973 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10974 {
10975         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10976                 return;
10977         if (prepass)
10978         {
10979                 // render screenspace normalmap to texture
10980                 GL_DepthMask(true);
10981                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10982                 RSurf_DrawBatch();
10983                 return;
10984         }
10985
10986         // bind lightmap texture
10987
10988         // water/refraction/reflection/camera surfaces have to be handled specially
10989         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10990         {
10991                 int start, end, startplaneindex;
10992                 for (start = 0;start < texturenumsurfaces;start = end)
10993                 {
10994                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10995                         if(startplaneindex < 0)
10996                         {
10997                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10998                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10999                                 end = start + 1;
11000                                 continue;
11001                         }
11002                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
11003                                 ;
11004                         // now that we have a batch using the same planeindex, render it
11005                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
11006                         {
11007                                 // render water or distortion background
11008                                 GL_DepthMask(true);
11009                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
11010                                 RSurf_DrawBatch();
11011                                 // blend surface on top
11012                                 GL_DepthMask(false);
11013                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
11014                                 RSurf_DrawBatch();
11015                         }
11016                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
11017                         {
11018                                 // render surface with reflection texture as input
11019                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11020                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
11021                                 RSurf_DrawBatch();
11022                         }
11023                 }
11024                 return;
11025         }
11026
11027         // render surface batch normally
11028         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11029         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
11030         RSurf_DrawBatch();
11031 }
11032
11033 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11034 {
11035         // OpenGL 1.3 path - anything not completely ancient
11036         qboolean applycolor;
11037         qboolean applyfog;
11038         int layerindex;
11039         const texturelayer_t *layer;
11040         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11041         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11042
11043         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11044         {
11045                 vec4_t layercolor;
11046                 int layertexrgbscale;
11047                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11048                 {
11049                         if (layerindex == 0)
11050                                 GL_AlphaTest(true);
11051                         else
11052                         {
11053                                 GL_AlphaTest(false);
11054                                 GL_DepthFunc(GL_EQUAL);
11055                         }
11056                 }
11057                 GL_DepthMask(layer->depthmask && writedepth);
11058                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11059                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11060                 {
11061                         layertexrgbscale = 4;
11062                         VectorScale(layer->color, 0.25f, layercolor);
11063                 }
11064                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11065                 {
11066                         layertexrgbscale = 2;
11067                         VectorScale(layer->color, 0.5f, layercolor);
11068                 }
11069                 else
11070                 {
11071                         layertexrgbscale = 1;
11072                         VectorScale(layer->color, 1.0f, layercolor);
11073                 }
11074                 layercolor[3] = layer->color[3];
11075                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11076                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11077                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11078                 switch (layer->type)
11079                 {
11080                 case TEXTURELAYERTYPE_LITTEXTURE:
11081                         // single-pass lightmapped texture with 2x rgbscale
11082                         R_Mesh_TexBind(0, r_texture_white);
11083                         R_Mesh_TexMatrix(0, NULL);
11084                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11085                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11086                         R_Mesh_TexBind(1, layer->texture);
11087                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11088                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11089                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11090                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11091                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11092                         else if (FAKELIGHT_ENABLED)
11093                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11094                         else if (rsurface.uselightmaptexture)
11095                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11096                         else
11097                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11098                         break;
11099                 case TEXTURELAYERTYPE_TEXTURE:
11100                         // singletexture unlit texture with transparency support
11101                         R_Mesh_TexBind(0, layer->texture);
11102                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11103                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11104                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11105                         R_Mesh_TexBind(1, 0);
11106                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11107                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11108                         break;
11109                 case TEXTURELAYERTYPE_FOG:
11110                         // singletexture fogging
11111                         if (layer->texture)
11112                         {
11113                                 R_Mesh_TexBind(0, layer->texture);
11114                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11115                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11116                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11117                         }
11118                         else
11119                         {
11120                                 R_Mesh_TexBind(0, 0);
11121                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11122                         }
11123                         R_Mesh_TexBind(1, 0);
11124                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11125                         // generate a color array for the fog pass
11126                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11127                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11128                         RSurf_DrawBatch();
11129                         break;
11130                 default:
11131                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11132                 }
11133         }
11134         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11135         {
11136                 GL_DepthFunc(GL_LEQUAL);
11137                 GL_AlphaTest(false);
11138         }
11139 }
11140
11141 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11142 {
11143         // OpenGL 1.1 - crusty old voodoo path
11144         qboolean applyfog;
11145         int layerindex;
11146         const texturelayer_t *layer;
11147         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11148         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11149
11150         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11151         {
11152                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11153                 {
11154                         if (layerindex == 0)
11155                                 GL_AlphaTest(true);
11156                         else
11157                         {
11158                                 GL_AlphaTest(false);
11159                                 GL_DepthFunc(GL_EQUAL);
11160                         }
11161                 }
11162                 GL_DepthMask(layer->depthmask && writedepth);
11163                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11164                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11165                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11166                 switch (layer->type)
11167                 {
11168                 case TEXTURELAYERTYPE_LITTEXTURE:
11169                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11170                         {
11171                                 // two-pass lit texture with 2x rgbscale
11172                                 // first the lightmap pass
11173                                 R_Mesh_TexBind(0, r_texture_white);
11174                                 R_Mesh_TexMatrix(0, NULL);
11175                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11176                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11177                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11178                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11179                                 else if (FAKELIGHT_ENABLED)
11180                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11181                                 else if (rsurface.uselightmaptexture)
11182                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11183                                 else
11184                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11185                                 // then apply the texture to it
11186                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11187                                 R_Mesh_TexBind(0, layer->texture);
11188                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11189                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11190                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11191                                 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);
11192                         }
11193                         else
11194                         {
11195                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11196                                 R_Mesh_TexBind(0, layer->texture);
11197                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11198                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11199                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11200                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11201                                         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);
11202                                 else if (FAKELIGHT_ENABLED)
11203                                         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);
11204                                 else
11205                                         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);
11206                         }
11207                         break;
11208                 case TEXTURELAYERTYPE_TEXTURE:
11209                         // singletexture unlit texture with transparency support
11210                         R_Mesh_TexBind(0, layer->texture);
11211                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11212                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11213                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11214                         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);
11215                         break;
11216                 case TEXTURELAYERTYPE_FOG:
11217                         // singletexture fogging
11218                         if (layer->texture)
11219                         {
11220                                 R_Mesh_TexBind(0, layer->texture);
11221                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11222                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11223                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11224                         }
11225                         else
11226                         {
11227                                 R_Mesh_TexBind(0, 0);
11228                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11229                         }
11230                         // generate a color array for the fog pass
11231                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11232                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11233                         RSurf_DrawBatch();
11234                         break;
11235                 default:
11236                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11237                 }
11238         }
11239         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11240         {
11241                 GL_DepthFunc(GL_LEQUAL);
11242                 GL_AlphaTest(false);
11243         }
11244 }
11245
11246 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11247 {
11248         int vi;
11249         int j;
11250         r_vertexgeneric_t *batchvertex;
11251         float c[4];
11252
11253 //      R_Mesh_ResetTextureState();
11254         R_SetupShader_Generic_NoTexture(false, false);
11255
11256         if(rsurface.texture && rsurface.texture->currentskinframe)
11257         {
11258                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11259                 c[3] *= rsurface.texture->currentalpha;
11260         }
11261         else
11262         {
11263                 c[0] = 1;
11264                 c[1] = 0;
11265                 c[2] = 1;
11266                 c[3] = 1;
11267         }
11268
11269         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11270         {
11271                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11272                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11273                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11274         }
11275
11276         // brighten it up (as texture value 127 means "unlit")
11277         c[0] *= 2 * r_refdef.view.colorscale;
11278         c[1] *= 2 * r_refdef.view.colorscale;
11279         c[2] *= 2 * r_refdef.view.colorscale;
11280
11281         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11282                 c[3] *= r_wateralpha.value;
11283
11284         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11285         {
11286                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11287                 GL_DepthMask(false);
11288         }
11289         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11290         {
11291                 GL_BlendFunc(GL_ONE, GL_ONE);
11292                 GL_DepthMask(false);
11293         }
11294         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11295         {
11296                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11297                 GL_DepthMask(false);
11298         }
11299         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11300         {
11301                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11302                 GL_DepthMask(false);
11303         }
11304         else
11305         {
11306                 GL_BlendFunc(GL_ONE, GL_ZERO);
11307                 GL_DepthMask(writedepth);
11308         }
11309
11310         if (r_showsurfaces.integer == 3)
11311         {
11312                 rsurface.passcolor4f = NULL;
11313
11314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11315                 {
11316                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11317
11318                         rsurface.passcolor4f = NULL;
11319                         rsurface.passcolor4f_vertexbuffer = 0;
11320                         rsurface.passcolor4f_bufferoffset = 0;
11321                 }
11322                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11323                 {
11324                         qboolean applycolor = true;
11325                         float one = 1.0;
11326
11327                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11328
11329                         r_refdef.lightmapintensity = 1;
11330                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11331                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11332                 }
11333                 else if (FAKELIGHT_ENABLED)
11334                 {
11335                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11336
11337                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11338                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11339                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11340                 }
11341                 else
11342                 {
11343                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11344
11345                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11346                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11347                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11348                 }
11349
11350                 if(!rsurface.passcolor4f)
11351                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11352
11353                 RSurf_DrawBatch_GL11_ApplyAmbient();
11354                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11355                 if(r_refdef.fogenabled)
11356                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11357                 RSurf_DrawBatch_GL11_ClampColor();
11358
11359                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11360                 R_SetupShader_Generic_NoTexture(false, false);
11361                 RSurf_DrawBatch();
11362         }
11363         else if (!r_refdef.view.showdebug)
11364         {
11365                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11366                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11367                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11368                 {
11369                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11370                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11371                 }
11372                 R_Mesh_PrepareVertices_Generic_Unlock();
11373                 RSurf_DrawBatch();
11374         }
11375         else if (r_showsurfaces.integer == 4)
11376         {
11377                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11378                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11379                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11380                 {
11381                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11382                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11383                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11384                 }
11385                 R_Mesh_PrepareVertices_Generic_Unlock();
11386                 RSurf_DrawBatch();
11387         }
11388         else if (r_showsurfaces.integer == 2)
11389         {
11390                 const int *e;
11391                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11392                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11393                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11394                 {
11395                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11396                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11397                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11398                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11399                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11400                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11401                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11402                 }
11403                 R_Mesh_PrepareVertices_Generic_Unlock();
11404                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11405         }
11406         else
11407         {
11408                 int texturesurfaceindex;
11409                 int k;
11410                 const msurface_t *surface;
11411                 float surfacecolor4f[4];
11412                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11413                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11414                 vi = 0;
11415                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11416                 {
11417                         surface = texturesurfacelist[texturesurfaceindex];
11418                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11419                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11420                         for (j = 0;j < surface->num_vertices;j++)
11421                         {
11422                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11423                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11424                                 vi++;
11425                         }
11426                 }
11427                 R_Mesh_PrepareVertices_Generic_Unlock();
11428                 RSurf_DrawBatch();
11429         }
11430 }
11431
11432 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11433 {
11434         CHECKGLERROR
11435         RSurf_SetupDepthAndCulling();
11436         if (r_showsurfaces.integer)
11437         {
11438                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11439                 return;
11440         }
11441         switch (vid.renderpath)
11442         {
11443         case RENDERPATH_GL20:
11444         case RENDERPATH_D3D9:
11445         case RENDERPATH_D3D10:
11446         case RENDERPATH_D3D11:
11447         case RENDERPATH_SOFT:
11448         case RENDERPATH_GLES2:
11449                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11450                 break;
11451         case RENDERPATH_GL13:
11452         case RENDERPATH_GLES1:
11453                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11454                 break;
11455         case RENDERPATH_GL11:
11456                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11457                 break;
11458         }
11459         CHECKGLERROR
11460 }
11461
11462 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11463 {
11464         CHECKGLERROR
11465         RSurf_SetupDepthAndCulling();
11466         if (r_showsurfaces.integer)
11467         {
11468                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11469                 return;
11470         }
11471         switch (vid.renderpath)
11472         {
11473         case RENDERPATH_GL20:
11474         case RENDERPATH_D3D9:
11475         case RENDERPATH_D3D10:
11476         case RENDERPATH_D3D11:
11477         case RENDERPATH_SOFT:
11478         case RENDERPATH_GLES2:
11479                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11480                 break;
11481         case RENDERPATH_GL13:
11482         case RENDERPATH_GLES1:
11483                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11484                 break;
11485         case RENDERPATH_GL11:
11486                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11487                 break;
11488         }
11489         CHECKGLERROR
11490 }
11491
11492 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11493 {
11494         int i, j;
11495         int texturenumsurfaces, endsurface;
11496         texture_t *texture;
11497         const msurface_t *surface;
11498         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11499
11500         // if the model is static it doesn't matter what value we give for
11501         // wantnormals and wanttangents, so this logic uses only rules applicable
11502         // to a model, knowing that they are meaningless otherwise
11503         if (ent == r_refdef.scene.worldentity)
11504                 RSurf_ActiveWorldEntity();
11505         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11506                 RSurf_ActiveModelEntity(ent, false, false, false);
11507         else
11508         {
11509                 switch (vid.renderpath)
11510                 {
11511                 case RENDERPATH_GL20:
11512                 case RENDERPATH_D3D9:
11513                 case RENDERPATH_D3D10:
11514                 case RENDERPATH_D3D11:
11515                 case RENDERPATH_SOFT:
11516                 case RENDERPATH_GLES2:
11517                         RSurf_ActiveModelEntity(ent, true, true, false);
11518                         break;
11519                 case RENDERPATH_GL11:
11520                 case RENDERPATH_GL13:
11521                 case RENDERPATH_GLES1:
11522                         RSurf_ActiveModelEntity(ent, true, false, false);
11523                         break;
11524                 }
11525         }
11526
11527         if (r_transparentdepthmasking.integer)
11528         {
11529                 qboolean setup = false;
11530                 for (i = 0;i < numsurfaces;i = j)
11531                 {
11532                         j = i + 1;
11533                         surface = rsurface.modelsurfaces + surfacelist[i];
11534                         texture = surface->texture;
11535                         rsurface.texture = R_GetCurrentTexture(texture);
11536                         rsurface.lightmaptexture = NULL;
11537                         rsurface.deluxemaptexture = NULL;
11538                         rsurface.uselightmaptexture = false;
11539                         // scan ahead until we find a different texture
11540                         endsurface = min(i + 1024, numsurfaces);
11541                         texturenumsurfaces = 0;
11542                         texturesurfacelist[texturenumsurfaces++] = surface;
11543                         for (;j < endsurface;j++)
11544                         {
11545                                 surface = rsurface.modelsurfaces + surfacelist[j];
11546                                 if (texture != surface->texture)
11547                                         break;
11548                                 texturesurfacelist[texturenumsurfaces++] = surface;
11549                         }
11550                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11551                                 continue;
11552                         // render the range of surfaces as depth
11553                         if (!setup)
11554                         {
11555                                 setup = true;
11556                                 GL_ColorMask(0,0,0,0);
11557                                 GL_Color(1,1,1,1);
11558                                 GL_DepthTest(true);
11559                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11560                                 GL_DepthMask(true);
11561 //                              R_Mesh_ResetTextureState();
11562                         }
11563                         RSurf_SetupDepthAndCulling();
11564                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11565                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11566                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11567                         RSurf_DrawBatch();
11568                 }
11569                 if (setup)
11570                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11571         }
11572
11573         for (i = 0;i < numsurfaces;i = j)
11574         {
11575                 j = i + 1;
11576                 surface = rsurface.modelsurfaces + surfacelist[i];
11577                 texture = surface->texture;
11578                 rsurface.texture = R_GetCurrentTexture(texture);
11579                 // scan ahead until we find a different texture
11580                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11581                 texturenumsurfaces = 0;
11582                 texturesurfacelist[texturenumsurfaces++] = surface;
11583                 if(FAKELIGHT_ENABLED)
11584                 {
11585                         rsurface.lightmaptexture = NULL;
11586                         rsurface.deluxemaptexture = NULL;
11587                         rsurface.uselightmaptexture = false;
11588                         for (;j < endsurface;j++)
11589                         {
11590                                 surface = rsurface.modelsurfaces + surfacelist[j];
11591                                 if (texture != surface->texture)
11592                                         break;
11593                                 texturesurfacelist[texturenumsurfaces++] = surface;
11594                         }
11595                 }
11596                 else
11597                 {
11598                         rsurface.lightmaptexture = surface->lightmaptexture;
11599                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11600                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11601                         for (;j < endsurface;j++)
11602                         {
11603                                 surface = rsurface.modelsurfaces + surfacelist[j];
11604                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11605                                         break;
11606                                 texturesurfacelist[texturenumsurfaces++] = surface;
11607                         }
11608                 }
11609                 // render the range of surfaces
11610                 if (ent == r_refdef.scene.worldentity)
11611                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11612                 else
11613                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11614         }
11615         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11616 }
11617
11618 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11619 {
11620         // transparent surfaces get pushed off into the transparent queue
11621         int surfacelistindex;
11622         const msurface_t *surface;
11623         vec3_t tempcenter, center;
11624         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11625         {
11626                 surface = texturesurfacelist[surfacelistindex];
11627                 if (r_transparent_sortsurfacesbynearest.integer)
11628                 {
11629                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11630                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11631                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11632                 }
11633                 else
11634                 {
11635                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11636                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11637                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11638                 }
11639                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11640                 if (rsurface.entity->transparent_offset) // transparent offset
11641                 {
11642                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11643                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11644                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11645                 }
11646                 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);
11647         }
11648 }
11649
11650 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11651 {
11652         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11653                 return;
11654         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11655                 return;
11656         RSurf_SetupDepthAndCulling();
11657         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11658         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11659         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11660         RSurf_DrawBatch();
11661 }
11662
11663 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11664 {
11665         CHECKGLERROR
11666         if (depthonly)
11667                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11668         else if (prepass)
11669         {
11670                 if (!rsurface.texture->currentnumlayers)
11671                         return;
11672                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11673                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11674                 else
11675                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11676         }
11677         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11678                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11679         else if (!rsurface.texture->currentnumlayers)
11680                 return;
11681         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11682         {
11683                 // in the deferred case, transparent surfaces were queued during prepass
11684                 if (!r_shadow_usingdeferredprepass)
11685                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11686         }
11687         else
11688         {
11689                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11690                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11691         }
11692         CHECKGLERROR
11693 }
11694
11695 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11696 {
11697         int i, j;
11698         texture_t *texture;
11699         R_FrameData_SetMark();
11700         // break the surface list down into batches by texture and use of lightmapping
11701         for (i = 0;i < numsurfaces;i = j)
11702         {
11703                 j = i + 1;
11704                 // texture is the base texture pointer, rsurface.texture is the
11705                 // current frame/skin the texture is directing us to use (for example
11706                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11707                 // use skin 1 instead)
11708                 texture = surfacelist[i]->texture;
11709                 rsurface.texture = R_GetCurrentTexture(texture);
11710                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11711                 {
11712                         // if this texture is not the kind we want, skip ahead to the next one
11713                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11714                                 ;
11715                         continue;
11716                 }
11717                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11718                 {
11719                         rsurface.lightmaptexture = NULL;
11720                         rsurface.deluxemaptexture = NULL;
11721                         rsurface.uselightmaptexture = false;
11722                         // simply scan ahead until we find a different texture or lightmap state
11723                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11724                                 ;
11725                 }
11726                 else
11727                 {
11728                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11729                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11730                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11731                         // simply scan ahead until we find a different texture or lightmap state
11732                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11733                                 ;
11734                 }
11735                 // render the range of surfaces
11736                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11737         }
11738         R_FrameData_ReturnToMark();
11739 }
11740
11741 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11742 {
11743         CHECKGLERROR
11744         if (depthonly)
11745                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11746         else if (prepass)
11747         {
11748                 if (!rsurface.texture->currentnumlayers)
11749                         return;
11750                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11751                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11752                 else
11753                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11754         }
11755         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11756                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11757         else if (!rsurface.texture->currentnumlayers)
11758                 return;
11759         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11760         {
11761                 // in the deferred case, transparent surfaces were queued during prepass
11762                 if (!r_shadow_usingdeferredprepass)
11763                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11764         }
11765         else
11766         {
11767                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11768                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11769         }
11770         CHECKGLERROR
11771 }
11772
11773 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11774 {
11775         int i, j;
11776         texture_t *texture;
11777         R_FrameData_SetMark();
11778         // break the surface list down into batches by texture and use of lightmapping
11779         for (i = 0;i < numsurfaces;i = j)
11780         {
11781                 j = i + 1;
11782                 // texture is the base texture pointer, rsurface.texture is the
11783                 // current frame/skin the texture is directing us to use (for example
11784                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11785                 // use skin 1 instead)
11786                 texture = surfacelist[i]->texture;
11787                 rsurface.texture = R_GetCurrentTexture(texture);
11788                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11789                 {
11790                         // if this texture is not the kind we want, skip ahead to the next one
11791                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11792                                 ;
11793                         continue;
11794                 }
11795                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11796                 {
11797                         rsurface.lightmaptexture = NULL;
11798                         rsurface.deluxemaptexture = NULL;
11799                         rsurface.uselightmaptexture = false;
11800                         // simply scan ahead until we find a different texture or lightmap state
11801                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11802                                 ;
11803                 }
11804                 else
11805                 {
11806                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11807                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11808                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11809                         // simply scan ahead until we find a different texture or lightmap state
11810                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11811                                 ;
11812                 }
11813                 // render the range of surfaces
11814                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11815         }
11816         R_FrameData_ReturnToMark();
11817 }
11818
11819 float locboxvertex3f[6*4*3] =
11820 {
11821         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11822         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11823         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11824         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11825         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11826         1,0,0, 0,0,0, 0,1,0, 1,1,0
11827 };
11828
11829 unsigned short locboxelements[6*2*3] =
11830 {
11831          0, 1, 2, 0, 2, 3,
11832          4, 5, 6, 4, 6, 7,
11833          8, 9,10, 8,10,11,
11834         12,13,14, 12,14,15,
11835         16,17,18, 16,18,19,
11836         20,21,22, 20,22,23
11837 };
11838
11839 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11840 {
11841         int i, j;
11842         cl_locnode_t *loc = (cl_locnode_t *)ent;
11843         vec3_t mins, size;
11844         float vertex3f[6*4*3];
11845         CHECKGLERROR
11846         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11847         GL_DepthMask(false);
11848         GL_DepthRange(0, 1);
11849         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11850         GL_DepthTest(true);
11851         GL_CullFace(GL_NONE);
11852         R_EntityMatrix(&identitymatrix);
11853
11854 //      R_Mesh_ResetTextureState();
11855
11856         i = surfacelist[0];
11857         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11858                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11859                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11860                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11861
11862         if (VectorCompare(loc->mins, loc->maxs))
11863         {
11864                 VectorSet(size, 2, 2, 2);
11865                 VectorMA(loc->mins, -0.5f, size, mins);
11866         }
11867         else
11868         {
11869                 VectorCopy(loc->mins, mins);
11870                 VectorSubtract(loc->maxs, loc->mins, size);
11871         }
11872
11873         for (i = 0;i < 6*4*3;)
11874                 for (j = 0;j < 3;j++, i++)
11875                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11876
11877         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11878         R_SetupShader_Generic_NoTexture(false, false);
11879         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11880 }
11881
11882 void R_DrawLocs(void)
11883 {
11884         int index;
11885         cl_locnode_t *loc, *nearestloc;
11886         vec3_t center;
11887         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11888         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11889         {
11890                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11891                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11892         }
11893 }
11894
11895 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11896 {
11897         if (decalsystem->decals)
11898                 Mem_Free(decalsystem->decals);
11899         memset(decalsystem, 0, sizeof(*decalsystem));
11900 }
11901
11902 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)
11903 {
11904         tridecal_t *decal;
11905         tridecal_t *decals;
11906         int i;
11907
11908         // expand or initialize the system
11909         if (decalsystem->maxdecals <= decalsystem->numdecals)
11910         {
11911                 decalsystem_t old = *decalsystem;
11912                 qboolean useshortelements;
11913                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11914                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11915                 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)));
11916                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11917                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11918                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11919                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11920                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11921                 if (decalsystem->numdecals)
11922                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11923                 if (old.decals)
11924                         Mem_Free(old.decals);
11925                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11926                         decalsystem->element3i[i] = i;
11927                 if (useshortelements)
11928                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11929                                 decalsystem->element3s[i] = i;
11930         }
11931
11932         // grab a decal and search for another free slot for the next one
11933         decals = decalsystem->decals;
11934         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11935         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11936                 ;
11937         decalsystem->freedecal = i;
11938         if (decalsystem->numdecals <= i)
11939                 decalsystem->numdecals = i + 1;
11940
11941         // initialize the decal
11942         decal->lived = 0;
11943         decal->triangleindex = triangleindex;
11944         decal->surfaceindex = surfaceindex;
11945         decal->decalsequence = decalsequence;
11946         decal->color4f[0][0] = c0[0];
11947         decal->color4f[0][1] = c0[1];
11948         decal->color4f[0][2] = c0[2];
11949         decal->color4f[0][3] = 1;
11950         decal->color4f[1][0] = c1[0];
11951         decal->color4f[1][1] = c1[1];
11952         decal->color4f[1][2] = c1[2];
11953         decal->color4f[1][3] = 1;
11954         decal->color4f[2][0] = c2[0];
11955         decal->color4f[2][1] = c2[1];
11956         decal->color4f[2][2] = c2[2];
11957         decal->color4f[2][3] = 1;
11958         decal->vertex3f[0][0] = v0[0];
11959         decal->vertex3f[0][1] = v0[1];
11960         decal->vertex3f[0][2] = v0[2];
11961         decal->vertex3f[1][0] = v1[0];
11962         decal->vertex3f[1][1] = v1[1];
11963         decal->vertex3f[1][2] = v1[2];
11964         decal->vertex3f[2][0] = v2[0];
11965         decal->vertex3f[2][1] = v2[1];
11966         decal->vertex3f[2][2] = v2[2];
11967         decal->texcoord2f[0][0] = t0[0];
11968         decal->texcoord2f[0][1] = t0[1];
11969         decal->texcoord2f[1][0] = t1[0];
11970         decal->texcoord2f[1][1] = t1[1];
11971         decal->texcoord2f[2][0] = t2[0];
11972         decal->texcoord2f[2][1] = t2[1];
11973         TriangleNormal(v0, v1, v2, decal->plane);
11974         VectorNormalize(decal->plane);
11975         decal->plane[3] = DotProduct(v0, decal->plane);
11976 }
11977
11978 extern cvar_t cl_decals_bias;
11979 extern cvar_t cl_decals_models;
11980 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11981 // baseparms, parms, temps
11982 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)
11983 {
11984         int cornerindex;
11985         int index;
11986         float v[9][3];
11987         const float *vertex3f;
11988         const float *normal3f;
11989         int numpoints;
11990         float points[2][9][3];
11991         float temp[3];
11992         float tc[9][2];
11993         float f;
11994         float c[9][4];
11995         const int *e;
11996
11997         e = rsurface.modelelement3i + 3*triangleindex;
11998
11999         vertex3f = rsurface.modelvertex3f;
12000         normal3f = rsurface.modelnormal3f;
12001
12002         if (normal3f)
12003         {
12004                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12005                 {
12006                         index = 3*e[cornerindex];
12007                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
12008                 }
12009         }
12010         else
12011         {
12012                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12013                 {
12014                         index = 3*e[cornerindex];
12015                         VectorCopy(vertex3f + index, v[cornerindex]);
12016                 }
12017         }
12018
12019         // cull backfaces
12020         //TriangleNormal(v[0], v[1], v[2], normal);
12021         //if (DotProduct(normal, localnormal) < 0.0f)
12022         //      continue;
12023         // clip by each of the box planes formed from the projection matrix
12024         // if anything survives, we emit the decal
12025         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]);
12026         if (numpoints < 3)
12027                 return;
12028         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]);
12029         if (numpoints < 3)
12030                 return;
12031         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]);
12032         if (numpoints < 3)
12033                 return;
12034         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]);
12035         if (numpoints < 3)
12036                 return;
12037         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]);
12038         if (numpoints < 3)
12039                 return;
12040         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]);
12041         if (numpoints < 3)
12042                 return;
12043         // some part of the triangle survived, so we have to accept it...
12044         if (dynamic)
12045         {
12046                 // dynamic always uses the original triangle
12047                 numpoints = 3;
12048                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12049                 {
12050                         index = 3*e[cornerindex];
12051                         VectorCopy(vertex3f + index, v[cornerindex]);
12052                 }
12053         }
12054         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12055         {
12056                 // convert vertex positions to texcoords
12057                 Matrix4x4_Transform(projection, v[cornerindex], temp);
12058                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12059                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12060                 // calculate distance fade from the projection origin
12061                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12062                 f = bound(0.0f, f, 1.0f);
12063                 c[cornerindex][0] = r * f;
12064                 c[cornerindex][1] = g * f;
12065                 c[cornerindex][2] = b * f;
12066                 c[cornerindex][3] = 1.0f;
12067                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12068         }
12069         if (dynamic)
12070                 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);
12071         else
12072                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12073                         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);
12074 }
12075 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)
12076 {
12077         matrix4x4_t projection;
12078         decalsystem_t *decalsystem;
12079         qboolean dynamic;
12080         dp_model_t *model;
12081         const msurface_t *surface;
12082         const msurface_t *surfaces;
12083         const int *surfacelist;
12084         const texture_t *texture;
12085         int numtriangles;
12086         int numsurfacelist;
12087         int surfacelistindex;
12088         int surfaceindex;
12089         int triangleindex;
12090         float localorigin[3];
12091         float localnormal[3];
12092         float localmins[3];
12093         float localmaxs[3];
12094         float localsize;
12095         //float normal[3];
12096         float planes[6][4];
12097         float angles[3];
12098         bih_t *bih;
12099         int bih_triangles_count;
12100         int bih_triangles[256];
12101         int bih_surfaces[256];
12102
12103         decalsystem = &ent->decalsystem;
12104         model = ent->model;
12105         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12106         {
12107                 R_DecalSystem_Reset(&ent->decalsystem);
12108                 return;
12109         }
12110
12111         if (!model->brush.data_leafs && !cl_decals_models.integer)
12112         {
12113                 if (decalsystem->model)
12114                         R_DecalSystem_Reset(decalsystem);
12115                 return;
12116         }
12117
12118         if (decalsystem->model != model)
12119                 R_DecalSystem_Reset(decalsystem);
12120         decalsystem->model = model;
12121
12122         RSurf_ActiveModelEntity(ent, true, false, false);
12123
12124         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12125         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12126         VectorNormalize(localnormal);
12127         localsize = worldsize*rsurface.inversematrixscale;
12128         localmins[0] = localorigin[0] - localsize;
12129         localmins[1] = localorigin[1] - localsize;
12130         localmins[2] = localorigin[2] - localsize;
12131         localmaxs[0] = localorigin[0] + localsize;
12132         localmaxs[1] = localorigin[1] + localsize;
12133         localmaxs[2] = localorigin[2] + localsize;
12134
12135         //VectorCopy(localnormal, planes[4]);
12136         //VectorVectors(planes[4], planes[2], planes[0]);
12137         AnglesFromVectors(angles, localnormal, NULL, false);
12138         AngleVectors(angles, planes[0], planes[2], planes[4]);
12139         VectorNegate(planes[0], planes[1]);
12140         VectorNegate(planes[2], planes[3]);
12141         VectorNegate(planes[4], planes[5]);
12142         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12143         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12144         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12145         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12146         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12147         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12148
12149 #if 1
12150 // works
12151 {
12152         matrix4x4_t forwardprojection;
12153         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12154         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12155 }
12156 #else
12157 // broken
12158 {
12159         float projectionvector[4][3];
12160         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12161         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12162         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12163         projectionvector[0][0] = planes[0][0] * ilocalsize;
12164         projectionvector[0][1] = planes[1][0] * ilocalsize;
12165         projectionvector[0][2] = planes[2][0] * ilocalsize;
12166         projectionvector[1][0] = planes[0][1] * ilocalsize;
12167         projectionvector[1][1] = planes[1][1] * ilocalsize;
12168         projectionvector[1][2] = planes[2][1] * ilocalsize;
12169         projectionvector[2][0] = planes[0][2] * ilocalsize;
12170         projectionvector[2][1] = planes[1][2] * ilocalsize;
12171         projectionvector[2][2] = planes[2][2] * ilocalsize;
12172         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12173         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12174         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12175         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12176 }
12177 #endif
12178
12179         dynamic = model->surfmesh.isanimated;
12180         numsurfacelist = model->nummodelsurfaces;
12181         surfacelist = model->sortedmodelsurfaces;
12182         surfaces = model->data_surfaces;
12183
12184         bih = NULL;
12185         bih_triangles_count = -1;
12186         if(!dynamic)
12187         {
12188                 if(model->render_bih.numleafs)
12189                         bih = &model->render_bih;
12190                 else if(model->collision_bih.numleafs)
12191                         bih = &model->collision_bih;
12192         }
12193         if(bih)
12194                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12195         if(bih_triangles_count == 0)
12196                 return;
12197         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12198                 return;
12199         if(bih_triangles_count > 0)
12200         {
12201                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12202                 {
12203                         surfaceindex = bih_surfaces[triangleindex];
12204                         surface = surfaces + surfaceindex;
12205                         texture = surface->texture;
12206                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12207                                 continue;
12208                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12209                                 continue;
12210                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12211                 }
12212         }
12213         else
12214         {
12215                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12216                 {
12217                         surfaceindex = surfacelist[surfacelistindex];
12218                         surface = surfaces + surfaceindex;
12219                         // check cull box first because it rejects more than any other check
12220                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12221                                 continue;
12222                         // skip transparent surfaces
12223                         texture = surface->texture;
12224                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12225                                 continue;
12226                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12227                                 continue;
12228                         numtriangles = surface->num_triangles;
12229                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12230                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12231                 }
12232         }
12233 }
12234
12235 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12236 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)
12237 {
12238         int renderentityindex;
12239         float worldmins[3];
12240         float worldmaxs[3];
12241         entity_render_t *ent;
12242
12243         if (!cl_decals_newsystem.integer)
12244                 return;
12245
12246         worldmins[0] = worldorigin[0] - worldsize;
12247         worldmins[1] = worldorigin[1] - worldsize;
12248         worldmins[2] = worldorigin[2] - worldsize;
12249         worldmaxs[0] = worldorigin[0] + worldsize;
12250         worldmaxs[1] = worldorigin[1] + worldsize;
12251         worldmaxs[2] = worldorigin[2] + worldsize;
12252
12253         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12254
12255         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12256         {
12257                 ent = r_refdef.scene.entities[renderentityindex];
12258                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12259                         continue;
12260
12261                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12262         }
12263 }
12264
12265 typedef struct r_decalsystem_splatqueue_s
12266 {
12267         vec3_t worldorigin;
12268         vec3_t worldnormal;
12269         float color[4];
12270         float tcrange[4];
12271         float worldsize;
12272         unsigned int decalsequence;
12273 }
12274 r_decalsystem_splatqueue_t;
12275
12276 int r_decalsystem_numqueued = 0;
12277 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12278
12279 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)
12280 {
12281         r_decalsystem_splatqueue_t *queue;
12282
12283         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12284                 return;
12285
12286         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12287         VectorCopy(worldorigin, queue->worldorigin);
12288         VectorCopy(worldnormal, queue->worldnormal);
12289         Vector4Set(queue->color, r, g, b, a);
12290         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12291         queue->worldsize = worldsize;
12292         queue->decalsequence = cl.decalsequence++;
12293 }
12294
12295 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12296 {
12297         int i;
12298         r_decalsystem_splatqueue_t *queue;
12299
12300         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12301                 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);
12302         r_decalsystem_numqueued = 0;
12303 }
12304
12305 extern cvar_t cl_decals_max;
12306 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12307 {
12308         int i;
12309         decalsystem_t *decalsystem = &ent->decalsystem;
12310         int numdecals;
12311         unsigned int killsequence;
12312         tridecal_t *decal;
12313         float frametime;
12314         float lifetime;
12315
12316         if (!decalsystem->numdecals)
12317                 return;
12318
12319         if (r_showsurfaces.integer)
12320                 return;
12321
12322         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12323         {
12324                 R_DecalSystem_Reset(decalsystem);
12325                 return;
12326         }
12327
12328         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12329         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12330
12331         if (decalsystem->lastupdatetime)
12332                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12333         else
12334                 frametime = 0;
12335         decalsystem->lastupdatetime = r_refdef.scene.time;
12336         numdecals = decalsystem->numdecals;
12337
12338         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12339         {
12340                 if (decal->color4f[0][3])
12341                 {
12342                         decal->lived += frametime;
12343                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12344                         {
12345                                 memset(decal, 0, sizeof(*decal));
12346                                 if (decalsystem->freedecal > i)
12347                                         decalsystem->freedecal = i;
12348                         }
12349                 }
12350         }
12351         decal = decalsystem->decals;
12352         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12353                 numdecals--;
12354
12355         // collapse the array by shuffling the tail decals into the gaps
12356         for (;;)
12357         {
12358                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12359                         decalsystem->freedecal++;
12360                 if (decalsystem->freedecal == numdecals)
12361                         break;
12362                 decal[decalsystem->freedecal] = decal[--numdecals];
12363         }
12364
12365         decalsystem->numdecals = numdecals;
12366
12367         if (numdecals <= 0)
12368         {
12369                 // if there are no decals left, reset decalsystem
12370                 R_DecalSystem_Reset(decalsystem);
12371         }
12372 }
12373
12374 extern skinframe_t *decalskinframe;
12375 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12376 {
12377         int i;
12378         decalsystem_t *decalsystem = &ent->decalsystem;
12379         int numdecals;
12380         tridecal_t *decal;
12381         float faderate;
12382         float alpha;
12383         float *v3f;
12384         float *c4f;
12385         float *t2f;
12386         const int *e;
12387         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12388         int numtris = 0;
12389
12390         numdecals = decalsystem->numdecals;
12391         if (!numdecals)
12392                 return;
12393
12394         if (r_showsurfaces.integer)
12395                 return;
12396
12397         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12398         {
12399                 R_DecalSystem_Reset(decalsystem);
12400                 return;
12401         }
12402
12403         // if the model is static it doesn't matter what value we give for
12404         // wantnormals and wanttangents, so this logic uses only rules applicable
12405         // to a model, knowing that they are meaningless otherwise
12406         if (ent == r_refdef.scene.worldentity)
12407                 RSurf_ActiveWorldEntity();
12408         else
12409                 RSurf_ActiveModelEntity(ent, false, false, false);
12410
12411         decalsystem->lastupdatetime = r_refdef.scene.time;
12412
12413         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12414
12415         // update vertex positions for animated models
12416         v3f = decalsystem->vertex3f;
12417         c4f = decalsystem->color4f;
12418         t2f = decalsystem->texcoord2f;
12419         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12420         {
12421                 if (!decal->color4f[0][3])
12422                         continue;
12423
12424                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12425                         continue;
12426
12427                 // skip backfaces
12428                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12429                         continue;
12430
12431                 // update color values for fading decals
12432                 if (decal->lived >= cl_decals_time.value)
12433                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12434                 else
12435                         alpha = 1.0f;
12436
12437                 c4f[ 0] = decal->color4f[0][0] * alpha;
12438                 c4f[ 1] = decal->color4f[0][1] * alpha;
12439                 c4f[ 2] = decal->color4f[0][2] * alpha;
12440                 c4f[ 3] = 1;
12441                 c4f[ 4] = decal->color4f[1][0] * alpha;
12442                 c4f[ 5] = decal->color4f[1][1] * alpha;
12443                 c4f[ 6] = decal->color4f[1][2] * alpha;
12444                 c4f[ 7] = 1;
12445                 c4f[ 8] = decal->color4f[2][0] * alpha;
12446                 c4f[ 9] = decal->color4f[2][1] * alpha;
12447                 c4f[10] = decal->color4f[2][2] * alpha;
12448                 c4f[11] = 1;
12449
12450                 t2f[0] = decal->texcoord2f[0][0];
12451                 t2f[1] = decal->texcoord2f[0][1];
12452                 t2f[2] = decal->texcoord2f[1][0];
12453                 t2f[3] = decal->texcoord2f[1][1];
12454                 t2f[4] = decal->texcoord2f[2][0];
12455                 t2f[5] = decal->texcoord2f[2][1];
12456
12457                 // update vertex positions for animated models
12458                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12459                 {
12460                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12461                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12462                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12463                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12464                 }
12465                 else
12466                 {
12467                         VectorCopy(decal->vertex3f[0], v3f);
12468                         VectorCopy(decal->vertex3f[1], v3f + 3);
12469                         VectorCopy(decal->vertex3f[2], v3f + 6);
12470                 }
12471
12472                 if (r_refdef.fogenabled)
12473                 {
12474                         alpha = RSurf_FogVertex(v3f);
12475                         VectorScale(c4f, alpha, c4f);
12476                         alpha = RSurf_FogVertex(v3f + 3);
12477                         VectorScale(c4f + 4, alpha, c4f + 4);
12478                         alpha = RSurf_FogVertex(v3f + 6);
12479                         VectorScale(c4f + 8, alpha, c4f + 8);
12480                 }
12481
12482                 v3f += 9;
12483                 c4f += 12;
12484                 t2f += 6;
12485                 numtris++;
12486         }
12487
12488         if (numtris > 0)
12489         {
12490                 r_refdef.stats[r_stat_drawndecals] += numtris;
12491
12492                 // now render the decals all at once
12493                 // (this assumes they all use one particle font texture!)
12494                 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);
12495 //              R_Mesh_ResetTextureState();
12496                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12497                 GL_DepthMask(false);
12498                 GL_DepthRange(0, 1);
12499                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12500                 GL_DepthTest(true);
12501                 GL_CullFace(GL_NONE);
12502                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12503                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12504                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12505         }
12506 }
12507
12508 static void R_DrawModelDecals(void)
12509 {
12510         int i, numdecals;
12511
12512         // fade faster when there are too many decals
12513         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12514         for (i = 0;i < r_refdef.scene.numentities;i++)
12515                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12516
12517         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12518         for (i = 0;i < r_refdef.scene.numentities;i++)
12519                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12520                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12521
12522         R_DecalSystem_ApplySplatEntitiesQueue();
12523
12524         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12525         for (i = 0;i < r_refdef.scene.numentities;i++)
12526                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12527
12528         r_refdef.stats[r_stat_totaldecals] += numdecals;
12529
12530         if (r_showsurfaces.integer)
12531                 return;
12532
12533         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12534
12535         for (i = 0;i < r_refdef.scene.numentities;i++)
12536         {
12537                 if (!r_refdef.viewcache.entityvisible[i])
12538                         continue;
12539                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12540                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12541         }
12542 }
12543
12544 extern cvar_t mod_collision_bih;
12545 static void R_DrawDebugModel(void)
12546 {
12547         entity_render_t *ent = rsurface.entity;
12548         int i, j, flagsmask;
12549         const msurface_t *surface;
12550         dp_model_t *model = ent->model;
12551
12552         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12553                 return;
12554
12555         if (r_showoverdraw.value > 0)
12556         {
12557                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12558                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12559                 R_SetupShader_Generic_NoTexture(false, false);
12560                 GL_DepthTest(false);
12561                 GL_DepthMask(false);
12562                 GL_DepthRange(0, 1);
12563                 GL_BlendFunc(GL_ONE, GL_ONE);
12564                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12565                 {
12566                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12567                                 continue;
12568                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12569                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12570                         {
12571                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12572                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12573                                 if (!rsurface.texture->currentlayers->depthmask)
12574                                         GL_Color(c, 0, 0, 1.0f);
12575                                 else if (ent == r_refdef.scene.worldentity)
12576                                         GL_Color(c, c, c, 1.0f);
12577                                 else
12578                                         GL_Color(0, c, 0, 1.0f);
12579                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12580                                 RSurf_DrawBatch();
12581                         }
12582                 }
12583                 rsurface.texture = NULL;
12584         }
12585
12586         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12587
12588 //      R_Mesh_ResetTextureState();
12589         R_SetupShader_Generic_NoTexture(false, false);
12590         GL_DepthRange(0, 1);
12591         GL_DepthTest(!r_showdisabledepthtest.integer);
12592         GL_DepthMask(false);
12593         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12594
12595         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12596         {
12597                 int triangleindex;
12598                 int bihleafindex;
12599                 qboolean cullbox = false;
12600                 const q3mbrush_t *brush;
12601                 const bih_t *bih = &model->collision_bih;
12602                 const bih_leaf_t *bihleaf;
12603                 float vertex3f[3][3];
12604                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12605                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12606                 {
12607                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12608                                 continue;
12609                         switch (bihleaf->type)
12610                         {
12611                         case BIH_BRUSH:
12612                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12613                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12614                                 {
12615                                         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);
12616                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12617                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12618                                 }
12619                                 break;
12620                         case BIH_COLLISIONTRIANGLE:
12621                                 triangleindex = bihleaf->itemindex;
12622                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12623                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12624                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12625                                 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);
12626                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12627                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12628                                 break;
12629                         case BIH_RENDERTRIANGLE:
12630                                 triangleindex = bihleaf->itemindex;
12631                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12632                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12633                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12634                                 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);
12635                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12636                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12637                                 break;
12638                         }
12639                 }
12640         }
12641
12642         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12643
12644 #ifndef USE_GLES2
12645         if (r_showtris.integer && qglPolygonMode)
12646         {
12647                 if (r_showdisabledepthtest.integer)
12648                 {
12649                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12650                         GL_DepthMask(false);
12651                 }
12652                 else
12653                 {
12654                         GL_BlendFunc(GL_ONE, GL_ZERO);
12655                         GL_DepthMask(true);
12656                 }
12657                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12658                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12659                 {
12660                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12661                                 continue;
12662                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12663                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12664                         {
12665                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12666                                 if (!rsurface.texture->currentlayers->depthmask)
12667                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12668                                 else if (ent == r_refdef.scene.worldentity)
12669                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12670                                 else
12671                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12672                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12673                                 RSurf_DrawBatch();
12674                         }
12675                 }
12676                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12677                 rsurface.texture = NULL;
12678         }
12679
12680         if (r_shownormals.value != 0 && qglBegin)
12681         {
12682                 int l, k;
12683                 vec3_t v;
12684                 if (r_showdisabledepthtest.integer)
12685                 {
12686                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12687                         GL_DepthMask(false);
12688                 }
12689                 else
12690                 {
12691                         GL_BlendFunc(GL_ONE, GL_ZERO);
12692                         GL_DepthMask(true);
12693                 }
12694                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12695                 {
12696                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12697                                 continue;
12698                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12699                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12700                         {
12701                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12702                                 qglBegin(GL_LINES);
12703                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12704                                 {
12705                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12706                                         {
12707                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12708                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12709                                                 qglVertex3f(v[0], v[1], v[2]);
12710                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12711                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12712                                                 qglVertex3f(v[0], v[1], v[2]);
12713                                         }
12714                                 }
12715                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12716                                 {
12717                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12718                                         {
12719                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12720                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12721                                                 qglVertex3f(v[0], v[1], v[2]);
12722                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12723                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12724                                                 qglVertex3f(v[0], v[1], v[2]);
12725                                         }
12726                                 }
12727                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12728                                 {
12729                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12730                                         {
12731                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12732                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12733                                                 qglVertex3f(v[0], v[1], v[2]);
12734                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12735                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12736                                                 qglVertex3f(v[0], v[1], v[2]);
12737                                         }
12738                                 }
12739                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12740                                 {
12741                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12742                                         {
12743                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12744                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12745                                                 qglVertex3f(v[0], v[1], v[2]);
12746                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12747                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12748                                                 qglVertex3f(v[0], v[1], v[2]);
12749                                         }
12750                                 }
12751                                 qglEnd();
12752                                 CHECKGLERROR
12753                         }
12754                 }
12755                 rsurface.texture = NULL;
12756         }
12757 #endif
12758 }
12759
12760 int r_maxsurfacelist = 0;
12761 const msurface_t **r_surfacelist = NULL;
12762 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12763 {
12764         int i, j, endj, flagsmask;
12765         dp_model_t *model = r_refdef.scene.worldmodel;
12766         msurface_t *surfaces;
12767         unsigned char *update;
12768         int numsurfacelist = 0;
12769         if (model == NULL)
12770                 return;
12771
12772         if (r_maxsurfacelist < model->num_surfaces)
12773         {
12774                 r_maxsurfacelist = model->num_surfaces;
12775                 if (r_surfacelist)
12776                         Mem_Free((msurface_t**)r_surfacelist);
12777                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12778         }
12779
12780         RSurf_ActiveWorldEntity();
12781
12782         surfaces = model->data_surfaces;
12783         update = model->brushq1.lightmapupdateflags;
12784
12785         // update light styles on this submodel
12786         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12787         {
12788                 model_brush_lightstyleinfo_t *style;
12789                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12790                 {
12791                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12792                         {
12793                                 int *list = style->surfacelist;
12794                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12795                                 for (j = 0;j < style->numsurfaces;j++)
12796                                         update[list[j]] = true;
12797                         }
12798                 }
12799         }
12800
12801         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12802
12803         if (debug)
12804         {
12805                 R_DrawDebugModel();
12806                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12807                 return;
12808         }
12809
12810         rsurface.lightmaptexture = NULL;
12811         rsurface.deluxemaptexture = NULL;
12812         rsurface.uselightmaptexture = false;
12813         rsurface.texture = NULL;
12814         rsurface.rtlight = NULL;
12815         numsurfacelist = 0;
12816         // add visible surfaces to draw list
12817         for (i = 0;i < model->nummodelsurfaces;i++)
12818         {
12819                 j = model->sortedmodelsurfaces[i];
12820                 if (r_refdef.viewcache.world_surfacevisible[j])
12821                         r_surfacelist[numsurfacelist++] = surfaces + j;
12822         }
12823         // update lightmaps if needed
12824         if (model->brushq1.firstrender)
12825         {
12826                 model->brushq1.firstrender = false;
12827                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12828                         if (update[j])
12829                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12830         }
12831         else if (update)
12832         {
12833                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12834                         if (r_refdef.viewcache.world_surfacevisible[j])
12835                                 if (update[j])
12836                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12837         }
12838         // don't do anything if there were no surfaces
12839         if (!numsurfacelist)
12840         {
12841                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12842                 return;
12843         }
12844         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12845
12846         // add to stats if desired
12847         if (r_speeds.integer && !skysurfaces && !depthonly)
12848         {
12849                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12850                 for (j = 0;j < numsurfacelist;j++)
12851                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12852         }
12853
12854         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12855 }
12856
12857 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12858 {
12859         int i, j, endj, flagsmask;
12860         dp_model_t *model = ent->model;
12861         msurface_t *surfaces;
12862         unsigned char *update;
12863         int numsurfacelist = 0;
12864         if (model == NULL)
12865                 return;
12866
12867         if (r_maxsurfacelist < model->num_surfaces)
12868         {
12869                 r_maxsurfacelist = model->num_surfaces;
12870                 if (r_surfacelist)
12871                         Mem_Free((msurface_t **)r_surfacelist);
12872                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12873         }
12874
12875         // if the model is static it doesn't matter what value we give for
12876         // wantnormals and wanttangents, so this logic uses only rules applicable
12877         // to a model, knowing that they are meaningless otherwise
12878         if (ent == r_refdef.scene.worldentity)
12879                 RSurf_ActiveWorldEntity();
12880         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12881                 RSurf_ActiveModelEntity(ent, false, false, false);
12882         else if (prepass)
12883                 RSurf_ActiveModelEntity(ent, true, true, true);
12884         else if (depthonly)
12885         {
12886                 switch (vid.renderpath)
12887                 {
12888                 case RENDERPATH_GL20:
12889                 case RENDERPATH_D3D9:
12890                 case RENDERPATH_D3D10:
12891                 case RENDERPATH_D3D11:
12892                 case RENDERPATH_SOFT:
12893                 case RENDERPATH_GLES2:
12894                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12895                         break;
12896                 case RENDERPATH_GL11:
12897                 case RENDERPATH_GL13:
12898                 case RENDERPATH_GLES1:
12899                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12900                         break;
12901                 }
12902         }
12903         else
12904         {
12905                 switch (vid.renderpath)
12906                 {
12907                 case RENDERPATH_GL20:
12908                 case RENDERPATH_D3D9:
12909                 case RENDERPATH_D3D10:
12910                 case RENDERPATH_D3D11:
12911                 case RENDERPATH_SOFT:
12912                 case RENDERPATH_GLES2:
12913                         RSurf_ActiveModelEntity(ent, true, true, false);
12914                         break;
12915                 case RENDERPATH_GL11:
12916                 case RENDERPATH_GL13:
12917                 case RENDERPATH_GLES1:
12918                         RSurf_ActiveModelEntity(ent, true, false, false);
12919                         break;
12920                 }
12921         }
12922
12923         surfaces = model->data_surfaces;
12924         update = model->brushq1.lightmapupdateflags;
12925
12926         // update light styles
12927         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12928         {
12929                 model_brush_lightstyleinfo_t *style;
12930                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12931                 {
12932                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12933                         {
12934                                 int *list = style->surfacelist;
12935                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12936                                 for (j = 0;j < style->numsurfaces;j++)
12937                                         update[list[j]] = true;
12938                         }
12939                 }
12940         }
12941
12942         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12943
12944         if (debug)
12945         {
12946                 R_DrawDebugModel();
12947                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12948                 return;
12949         }
12950
12951         rsurface.lightmaptexture = NULL;
12952         rsurface.deluxemaptexture = NULL;
12953         rsurface.uselightmaptexture = false;
12954         rsurface.texture = NULL;
12955         rsurface.rtlight = NULL;
12956         numsurfacelist = 0;
12957         // add visible surfaces to draw list
12958         for (i = 0;i < model->nummodelsurfaces;i++)
12959                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12960         // don't do anything if there were no surfaces
12961         if (!numsurfacelist)
12962         {
12963                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12964                 return;
12965         }
12966         // update lightmaps if needed
12967         if (update)
12968         {
12969                 int updated = 0;
12970                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12971                 {
12972                         if (update[j])
12973                         {
12974                                 updated++;
12975                                 R_BuildLightMap(ent, surfaces + j);
12976                         }
12977                 }
12978         }
12979
12980         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12981
12982         // add to stats if desired
12983         if (r_speeds.integer && !skysurfaces && !depthonly)
12984         {
12985                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12986                 for (j = 0;j < numsurfacelist;j++)
12987                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12988         }
12989
12990         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12991 }
12992
12993 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12994 {
12995         static texture_t texture;
12996         static msurface_t surface;
12997         const msurface_t *surfacelist = &surface;
12998
12999         // fake enough texture and surface state to render this geometry
13000
13001         texture.update_lastrenderframe = -1; // regenerate this texture
13002         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13003         texture.basealpha = 1.0f;
13004         texture.currentskinframe = skinframe;
13005         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13006         texture.offsetmapping = OFFSETMAPPING_OFF;
13007         texture.offsetscale = 1;
13008         texture.specularscalemod = 1;
13009         texture.specularpowermod = 1;
13010         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
13011         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
13012         // JUST GREP FOR "specularscalemod = 1".
13013
13014         surface.texture = &texture;
13015         surface.num_triangles = numtriangles;
13016         surface.num_firsttriangle = firsttriangle;
13017         surface.num_vertices = numvertices;
13018         surface.num_firstvertex = firstvertex;
13019
13020         // now render it
13021         rsurface.texture = R_GetCurrentTexture(surface.texture);
13022         rsurface.lightmaptexture = NULL;
13023         rsurface.deluxemaptexture = NULL;
13024         rsurface.uselightmaptexture = false;
13025         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13026 }
13027
13028 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)
13029 {
13030         static msurface_t surface;
13031         const msurface_t *surfacelist = &surface;
13032
13033         // fake enough texture and surface state to render this geometry
13034         surface.texture = texture;
13035         surface.num_triangles = numtriangles;
13036         surface.num_firsttriangle = firsttriangle;
13037         surface.num_vertices = numvertices;
13038         surface.num_firstvertex = firstvertex;
13039
13040         // now render it
13041         rsurface.texture = R_GetCurrentTexture(surface.texture);
13042         rsurface.lightmaptexture = NULL;
13043         rsurface.deluxemaptexture = NULL;
13044         rsurface.uselightmaptexture = false;
13045         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13046 }