]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
New alternative to fullbright: r_fullbright_directed.
[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"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
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"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
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", "1", "increases shadowmap quality (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;
272 extern cvar_t v_glslgamma_2d;
273
274 extern qboolean v_flipped_state;
275
276 r_framebufferstate_t r_fb;
277
278 /// shadow volume bsp struct with automatically growing nodes buffer
279 svbsp_t r_svbsp;
280
281 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
282
283 rtexture_t *r_texture_blanknormalmap;
284 rtexture_t *r_texture_white;
285 rtexture_t *r_texture_grey128;
286 rtexture_t *r_texture_black;
287 rtexture_t *r_texture_notexture;
288 rtexture_t *r_texture_whitecube;
289 rtexture_t *r_texture_normalizationcube;
290 rtexture_t *r_texture_fogattenuation;
291 rtexture_t *r_texture_fogheighttexture;
292 rtexture_t *r_texture_gammaramps;
293 unsigned int r_texture_gammaramps_serial;
294 //rtexture_t *r_texture_fogintensity;
295 rtexture_t *r_texture_reflectcube;
296
297 // TODO: hash lookups?
298 typedef struct cubemapinfo_s
299 {
300         char basename[64];
301         rtexture_t *texture;
302 }
303 cubemapinfo_t;
304
305 int r_texture_numcubemaps;
306 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
307
308 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
309 unsigned int r_numqueries;
310 unsigned int r_maxqueries;
311
312 typedef struct r_qwskincache_s
313 {
314         char name[MAX_QPATH];
315         skinframe_t *skinframe;
316 }
317 r_qwskincache_t;
318
319 static r_qwskincache_t *r_qwskincache;
320 static int r_qwskincache_size;
321
322 /// vertex coordinates for a quad that covers the screen exactly
323 extern const float r_screenvertex3f[12];
324 extern const float r_d3dscreenvertex3f[12];
325 const float r_screenvertex3f[12] =
326 {
327         0, 0, 0,
328         1, 0, 0,
329         1, 1, 0,
330         0, 1, 0
331 };
332 const float r_d3dscreenvertex3f[12] =
333 {
334         0, 1, 0,
335         1, 1, 0,
336         1, 0, 0,
337         0, 0, 0
338 };
339
340 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
341 {
342         int i;
343         for (i = 0;i < verts;i++)
344         {
345                 out[0] = in[0] * r;
346                 out[1] = in[1] * g;
347                 out[2] = in[2] * b;
348                 out[3] = in[3];
349                 in += 4;
350                 out += 4;
351         }
352 }
353
354 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
355 {
356         int i;
357         for (i = 0;i < verts;i++)
358         {
359                 out[0] = r;
360                 out[1] = g;
361                 out[2] = b;
362                 out[3] = a;
363                 out += 4;
364         }
365 }
366
367 // FIXME: move this to client?
368 void FOG_clear(void)
369 {
370         if (gamemode == GAME_NEHAHRA)
371         {
372                 Cvar_Set("gl_fogenable", "0");
373                 Cvar_Set("gl_fogdensity", "0.2");
374                 Cvar_Set("gl_fogred", "0.3");
375                 Cvar_Set("gl_foggreen", "0.3");
376                 Cvar_Set("gl_fogblue", "0.3");
377         }
378         r_refdef.fog_density = 0;
379         r_refdef.fog_red = 0;
380         r_refdef.fog_green = 0;
381         r_refdef.fog_blue = 0;
382         r_refdef.fog_alpha = 1;
383         r_refdef.fog_start = 0;
384         r_refdef.fog_end = 16384;
385         r_refdef.fog_height = 1<<30;
386         r_refdef.fog_fadedepth = 128;
387         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
388 }
389
390 static void R_BuildBlankTextures(void)
391 {
392         unsigned char data[4];
393         data[2] = 128; // normal X
394         data[1] = 128; // normal Y
395         data[0] = 255; // normal Z
396         data[3] = 255; // height
397         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 255;
399         data[1] = 255;
400         data[2] = 255;
401         data[3] = 255;
402         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403         data[0] = 128;
404         data[1] = 128;
405         data[2] = 128;
406         data[3] = 255;
407         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
408         data[0] = 0;
409         data[1] = 0;
410         data[2] = 0;
411         data[3] = 255;
412         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildNoTexture(void)
416 {
417         int x, y;
418         unsigned char pix[16][16][4];
419         // this makes a light grey/dark grey checkerboard texture
420         for (y = 0;y < 16;y++)
421         {
422                 for (x = 0;x < 16;x++)
423                 {
424                         if ((y < 8) ^ (x < 8))
425                         {
426                                 pix[y][x][0] = 128;
427                                 pix[y][x][1] = 128;
428                                 pix[y][x][2] = 128;
429                                 pix[y][x][3] = 255;
430                         }
431                         else
432                         {
433                                 pix[y][x][0] = 64;
434                                 pix[y][x][1] = 64;
435                                 pix[y][x][2] = 64;
436                                 pix[y][x][3] = 255;
437                         }
438                 }
439         }
440         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
441 }
442
443 static void R_BuildWhiteCube(void)
444 {
445         unsigned char data[6*1*1*4];
446         memset(data, 255, sizeof(data));
447         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
448 }
449
450 static void R_BuildNormalizationCube(void)
451 {
452         int x, y, side;
453         vec3_t v;
454         vec_t s, t, intensity;
455 #define NORMSIZE 64
456         unsigned char *data;
457         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
458         for (side = 0;side < 6;side++)
459         {
460                 for (y = 0;y < NORMSIZE;y++)
461                 {
462                         for (x = 0;x < NORMSIZE;x++)
463                         {
464                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
466                                 switch(side)
467                                 {
468                                 default:
469                                 case 0:
470                                         v[0] = 1;
471                                         v[1] = -t;
472                                         v[2] = -s;
473                                         break;
474                                 case 1:
475                                         v[0] = -1;
476                                         v[1] = -t;
477                                         v[2] = s;
478                                         break;
479                                 case 2:
480                                         v[0] = s;
481                                         v[1] = 1;
482                                         v[2] = t;
483                                         break;
484                                 case 3:
485                                         v[0] = s;
486                                         v[1] = -1;
487                                         v[2] = -t;
488                                         break;
489                                 case 4:
490                                         v[0] = s;
491                                         v[1] = -t;
492                                         v[2] = 1;
493                                         break;
494                                 case 5:
495                                         v[0] = -s;
496                                         v[1] = -t;
497                                         v[2] = -1;
498                                         break;
499                                 }
500                                 intensity = 127.0f / sqrt(DotProduct(v, v));
501                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
502                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
503                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
504                                 data[((side*64+y)*64+x)*4+3] = 255;
505                         }
506                 }
507         }
508         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
509         Mem_Free(data);
510 }
511
512 static void R_BuildFogTexture(void)
513 {
514         int x, b;
515 #define FOGWIDTH 256
516         unsigned char data1[FOGWIDTH][4];
517         //unsigned char data2[FOGWIDTH][4];
518         double d, r, alpha;
519
520         r_refdef.fogmasktable_start = r_refdef.fog_start;
521         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
522         r_refdef.fogmasktable_range = r_refdef.fogrange;
523         r_refdef.fogmasktable_density = r_refdef.fog_density;
524
525         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
526         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
527         {
528                 d = (x * r - r_refdef.fogmasktable_start);
529                 if(developer_extra.integer)
530                         Con_DPrintf("%f ", d);
531                 d = max(0, d);
532                 if (r_fog_exp2.integer)
533                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
534                 else
535                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
536                 if(developer_extra.integer)
537                         Con_DPrintf(" : %f ", alpha);
538                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
539                 if(developer_extra.integer)
540                         Con_DPrintf(" = %f\n", alpha);
541                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
542         }
543
544         for (x = 0;x < FOGWIDTH;x++)
545         {
546                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
547                 data1[x][0] = b;
548                 data1[x][1] = b;
549                 data1[x][2] = b;
550                 data1[x][3] = 255;
551                 //data2[x][0] = 255 - b;
552                 //data2[x][1] = 255 - b;
553                 //data2[x][2] = 255 - b;
554                 //data2[x][3] = 255;
555         }
556         if (r_texture_fogattenuation)
557         {
558                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
560         }
561         else
562         {
563                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
564                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
565         }
566 }
567
568 static void R_BuildFogHeightTexture(void)
569 {
570         unsigned char *inpixels;
571         int size;
572         int x;
573         int y;
574         int j;
575         float c[4];
576         float f;
577         inpixels = NULL;
578         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
579         if (r_refdef.fogheighttexturename[0])
580                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
581         if (!inpixels)
582         {
583                 r_refdef.fog_height_tablesize = 0;
584                 if (r_texture_fogheighttexture)
585                         R_FreeTexture(r_texture_fogheighttexture);
586                 r_texture_fogheighttexture = NULL;
587                 if (r_refdef.fog_height_table2d)
588                         Mem_Free(r_refdef.fog_height_table2d);
589                 r_refdef.fog_height_table2d = NULL;
590                 if (r_refdef.fog_height_table1d)
591                         Mem_Free(r_refdef.fog_height_table1d);
592                 r_refdef.fog_height_table1d = NULL;
593                 return;
594         }
595         size = image_width;
596         r_refdef.fog_height_tablesize = size;
597         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
598         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
599         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
600         Mem_Free(inpixels);
601         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
602         // average fog color table accounting for every fog layer between a point
603         // and the camera.  (Note: attenuation is handled separately!)
604         for (y = 0;y < size;y++)
605         {
606                 for (x = 0;x < size;x++)
607                 {
608                         Vector4Clear(c);
609                         f = 0;
610                         if (x < y)
611                         {
612                                 for (j = x;j <= y;j++)
613                                 {
614                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
615                                         f++;
616                                 }
617                         }
618                         else
619                         {
620                                 for (j = x;j >= y;j--)
621                                 {
622                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
623                                         f++;
624                                 }
625                         }
626                         f = 1.0f / f;
627                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
629                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
630                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
631                 }
632         }
633         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
634 }
635
636 //=======================================================================================================================================================
637
638 static const char *builtinshaderstrings[] =
639 {
640 #include "shader_glsl.h"
641 0
642 };
643
644 const char *builtinhlslshaderstrings[] =
645 {
646 #include "shader_hlsl.h"
647 0
648 };
649
650 //=======================================================================================================================================================
651
652 typedef struct shaderpermutationinfo_s
653 {
654         const char *pretext;
655         const char *name;
656 }
657 shaderpermutationinfo_t;
658
659 typedef struct shadermodeinfo_s
660 {
661         const char *sourcebasename;
662         const char *extension;
663         const char **builtinshaderstrings;
664         const char *pretext;
665         const char *name;
666         char *filename;
667         char *builtinstring;
668         int builtincrc;
669 }
670 shadermodeinfo_t;
671
672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
674 {
675         {"#define USEDIFFUSE\n", " diffuse"},
676         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
677         {"#define USEVIEWTINT\n", " viewtint"},
678         {"#define USECOLORMAPPING\n", " colormapping"},
679         {"#define USESATURATION\n", " saturation"},
680         {"#define USEFOGINSIDE\n", " foginside"},
681         {"#define USEFOGOUTSIDE\n", " fogoutside"},
682         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
683         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
684         {"#define USEGAMMARAMPS\n", " gammaramps"},
685         {"#define USECUBEFILTER\n", " cubefilter"},
686         {"#define USEGLOW\n", " glow"},
687         {"#define USEBLOOM\n", " bloom"},
688         {"#define USESPECULAR\n", " specular"},
689         {"#define USEPOSTPROCESSING\n", " postprocessing"},
690         {"#define USEREFLECTION\n", " reflection"},
691         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
692         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
693         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
694         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
695         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
696         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
697         {"#define USEALPHAKILL\n", " alphakill"},
698         {"#define USEREFLECTCUBE\n", " reflectcube"},
699         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
700         {"#define USEBOUNCEGRID\n", " bouncegrid"},
701         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
702         {"#define USETRIPPY\n", " trippy"},
703         {"#define USEDEPTHRGB\n", " depthrgb"},
704         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
705         {"#define USESKELETAL\n", " skeletal"},
706         {"#define USEOCCLUDE\n", " occlude"}
707 };
708
709 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
710 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
711 {
712         // SHADERLANGUAGE_GLSL
713         {
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
729                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731         },
732         // SHADERLANGUAGE_HLSL
733         {
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
749                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
750                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
751         },
752 };
753
754 struct r_glsl_permutation_s;
755 typedef struct r_glsl_permutation_s
756 {
757         /// hash lookup data
758         struct r_glsl_permutation_s *hashnext;
759         unsigned int mode;
760         dpuint64 permutation;
761
762         /// indicates if we have tried compiling this permutation already
763         qboolean compiled;
764         /// 0 if compilation failed
765         int program;
766         // texture units assigned to each detected uniform
767         int tex_Texture_First;
768         int tex_Texture_Second;
769         int tex_Texture_GammaRamps;
770         int tex_Texture_Normal;
771         int tex_Texture_Color;
772         int tex_Texture_Gloss;
773         int tex_Texture_Glow;
774         int tex_Texture_SecondaryNormal;
775         int tex_Texture_SecondaryColor;
776         int tex_Texture_SecondaryGloss;
777         int tex_Texture_SecondaryGlow;
778         int tex_Texture_Pants;
779         int tex_Texture_Shirt;
780         int tex_Texture_FogHeightTexture;
781         int tex_Texture_FogMask;
782         int tex_Texture_Lightmap;
783         int tex_Texture_Deluxemap;
784         int tex_Texture_Attenuation;
785         int tex_Texture_Cube;
786         int tex_Texture_Refraction;
787         int tex_Texture_Reflection;
788         int tex_Texture_ShadowMap2D;
789         int tex_Texture_CubeProjection;
790         int tex_Texture_ScreenNormalMap;
791         int tex_Texture_ScreenDiffuse;
792         int tex_Texture_ScreenSpecular;
793         int tex_Texture_ReflectMask;
794         int tex_Texture_ReflectCube;
795         int tex_Texture_BounceGrid;
796         /// locations of detected uniforms in program object, or -1 if not found
797         int loc_Texture_First;
798         int loc_Texture_Second;
799         int loc_Texture_GammaRamps;
800         int loc_Texture_Normal;
801         int loc_Texture_Color;
802         int loc_Texture_Gloss;
803         int loc_Texture_Glow;
804         int loc_Texture_SecondaryNormal;
805         int loc_Texture_SecondaryColor;
806         int loc_Texture_SecondaryGloss;
807         int loc_Texture_SecondaryGlow;
808         int loc_Texture_Pants;
809         int loc_Texture_Shirt;
810         int loc_Texture_FogHeightTexture;
811         int loc_Texture_FogMask;
812         int loc_Texture_Lightmap;
813         int loc_Texture_Deluxemap;
814         int loc_Texture_Attenuation;
815         int loc_Texture_Cube;
816         int loc_Texture_Refraction;
817         int loc_Texture_Reflection;
818         int loc_Texture_ShadowMap2D;
819         int loc_Texture_CubeProjection;
820         int loc_Texture_ScreenNormalMap;
821         int loc_Texture_ScreenDiffuse;
822         int loc_Texture_ScreenSpecular;
823         int loc_Texture_ReflectMask;
824         int loc_Texture_ReflectCube;
825         int loc_Texture_BounceGrid;
826         int loc_Alpha;
827         int loc_BloomBlur_Parameters;
828         int loc_ClientTime;
829         int loc_Color_Ambient;
830         int loc_Color_Diffuse;
831         int loc_Color_Specular;
832         int loc_Color_Glow;
833         int loc_Color_Pants;
834         int loc_Color_Shirt;
835         int loc_DeferredColor_Ambient;
836         int loc_DeferredColor_Diffuse;
837         int loc_DeferredColor_Specular;
838         int loc_DeferredMod_Diffuse;
839         int loc_DeferredMod_Specular;
840         int loc_DistortScaleRefractReflect;
841         int loc_EyePosition;
842         int loc_FogColor;
843         int loc_FogHeightFade;
844         int loc_FogPlane;
845         int loc_FogPlaneViewDist;
846         int loc_FogRangeRecip;
847         int loc_LightColor;
848         int loc_LightDir;
849         int loc_LightPosition;
850         int loc_OffsetMapping_ScaleSteps;
851         int loc_OffsetMapping_LodDistance;
852         int loc_OffsetMapping_Bias;
853         int loc_PixelSize;
854         int loc_ReflectColor;
855         int loc_ReflectFactor;
856         int loc_ReflectOffset;
857         int loc_RefractColor;
858         int loc_Saturation;
859         int loc_ScreenCenterRefractReflect;
860         int loc_ScreenScaleRefractReflect;
861         int loc_ScreenToDepth;
862         int loc_ShadowMap_Parameters;
863         int loc_ShadowMap_TextureScale;
864         int loc_SpecularPower;
865         int loc_Skeletal_Transform12;
866         int loc_UserVec1;
867         int loc_UserVec2;
868         int loc_UserVec3;
869         int loc_UserVec4;
870         int loc_ViewTintColor;
871         int loc_ViewToLight;
872         int loc_ModelToLight;
873         int loc_TexMatrix;
874         int loc_BackgroundTexMatrix;
875         int loc_ModelViewProjectionMatrix;
876         int loc_ModelViewMatrix;
877         int loc_PixelToScreenTexCoord;
878         int loc_ModelToReflectCube;
879         int loc_ShadowMapMatrix;
880         int loc_BloomColorSubtract;
881         int loc_NormalmapScrollBlend;
882         int loc_BounceGridMatrix;
883         int loc_BounceGridIntensity;
884         /// uniform block bindings
885         int ubibind_Skeletal_Transform12_UniformBlock;
886         /// uniform block indices
887         int ubiloc_Skeletal_Transform12_UniformBlock;
888 }
889 r_glsl_permutation_t;
890
891 #define SHADERPERMUTATION_HASHSIZE 256
892
893
894 // non-degradable "lightweight" shader parameters to keep the permutations simpler
895 // these can NOT degrade! only use for simple stuff
896 enum
897 {
898         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
899         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
900         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
902         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
903         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
904         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
905         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
906         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
907         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
908         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
909         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
910         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
911         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
912 };
913 #define SHADERSTATICPARMS_COUNT 14
914
915 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
916 static int shaderstaticparms_count = 0;
917
918 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
919 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
920
921 extern qboolean r_shadow_shadowmapsampler;
922 extern int r_shadow_shadowmappcf;
923 qboolean R_CompileShader_CheckStaticParms(void)
924 {
925         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
926         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
927         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
928
929         // detect all
930         if (r_glsl_saturation_redcompensate.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
932         if (r_glsl_vertextextureblend_usebothalphas.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
934         if (r_shadow_glossexact.integer)
935                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
936         if (r_glsl_postprocess.integer)
937         {
938                 if (r_glsl_postprocess_uservec1_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
940                 if (r_glsl_postprocess_uservec2_enable.integer)
941                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
942                 if (r_glsl_postprocess_uservec3_enable.integer)
943                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
944                 if (r_glsl_postprocess_uservec4_enable.integer)
945                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
946         }
947         if (r_fxaa.integer)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
949         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
950                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
951
952         if (r_shadow_shadowmapsampler)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
954         if (r_shadow_shadowmappcf > 1)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
956         else if (r_shadow_shadowmappcf)
957                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
958         if (r_celshading.integer)
959                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
960         if (r_celoutlines.integer)
961                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
962
963         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
964 }
965
966 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
967         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
968                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
969         else \
970                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
971 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
972 {
973         shaderstaticparms_count = 0;
974
975         // emit all
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
988         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
989         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
990 }
991
992 /// information about each possible shader permutation
993 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
994 /// currently selected permutation
995 r_glsl_permutation_t *r_glsl_permutation;
996 /// storage for permutations linked in the hash table
997 memexpandablearray_t r_glsl_permutationarray;
998
999 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1000 {
1001         //unsigned int hashdepth = 0;
1002         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1003         r_glsl_permutation_t *p;
1004         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1005         {
1006                 if (p->mode == mode && p->permutation == permutation)
1007                 {
1008                         //if (hashdepth > 10)
1009                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1010                         return p;
1011                 }
1012                 //hashdepth++;
1013         }
1014         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1015         p->mode = mode;
1016         p->permutation = permutation;
1017         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1018         r_glsl_permutationhash[mode][hashindex] = p;
1019         //if (hashdepth > 10)
1020         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1021         return p;
1022 }
1023
1024 static char *R_ShaderStrCat(const char **strings)
1025 {
1026         char *string, *s;
1027         const char **p = strings;
1028         const char *t;
1029         size_t len = 0;
1030         for (p = strings;(t = *p);p++)
1031                 len += strlen(t);
1032         len++;
1033         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1034         len = 0;
1035         for (p = strings;(t = *p);p++)
1036         {
1037                 len = strlen(t);
1038                 memcpy(s, t, len);
1039                 s += len;
1040         }
1041         *s = 0;
1042         return string;
1043 }
1044
1045 static char *R_ShaderStrCat(const char **strings);
1046 static void R_InitShaderModeInfo(void)
1047 {
1048         int i, language;
1049         shadermodeinfo_t *modeinfo;
1050         // 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)
1051         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1052         {
1053                 for (i = 0; i < SHADERMODE_COUNT; i++)
1054                 {
1055                         char filename[MAX_QPATH];
1056                         modeinfo = &shadermodeinfo[language][i];
1057                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1058                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1059                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1060                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1061                 }
1062         }
1063 }
1064
1065 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1066 {
1067         char *shaderstring;
1068         // if the mode has no filename we have to return the builtin string
1069         if (builtinonly || !modeinfo->filename)
1070                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071         // note that FS_LoadFile appends a 0 byte to make it a valid string
1072         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1077                 return shaderstring;
1078         }
1079         // fall back to builtinstring
1080         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1081 }
1082
1083 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1084 {
1085         int i;
1086         int ubibind;
1087         int sampler;
1088         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1089         char *sourcestring;
1090         char permutationname[256];
1091         int vertstrings_count = 0;
1092         int geomstrings_count = 0;
1093         int fragstrings_count = 0;
1094         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1097
1098         if (p->compiled)
1099                 return;
1100         p->compiled = true;
1101         p->program = 0;
1102
1103         permutationname[0] = 0;
1104         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1105
1106         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107
1108         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1109         if(vid.support.glshaderversion >= 140)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117         }
1118         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1119         else if(vid.support.glshaderversion >= 130)
1120         {
1121                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1122                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1123                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1124                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1125                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1126                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1127         }
1128         // if we can do #version 120, we should (this adds the invariant keyword)
1129         else if(vid.support.glshaderversion >= 120)
1130         {
1131                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1132                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1133                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1134                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1135                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1136                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1137         }
1138         // GLES also adds several things from GLSL120
1139         switch(vid.renderpath)
1140         {
1141         case RENDERPATH_GLES2:
1142                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1143                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1144                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1145                 break;
1146         default:
1147                 break;
1148         }
1149
1150         // the first pretext is which type of shader to compile as
1151         // (later these will all be bound together as a program object)
1152         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1153         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1154         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1155
1156         // the second pretext is the mode (for example a light source)
1157         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1158         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1159         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1160         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1161
1162         // now add all the permutation pretexts
1163         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1164         {
1165                 if (permutation & (1ll<<i))
1166                 {
1167                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1169                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1170                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1171                 }
1172                 else
1173                 {
1174                         // keep line numbers correct
1175                         vertstrings_list[vertstrings_count++] = "\n";
1176                         geomstrings_list[geomstrings_count++] = "\n";
1177                         fragstrings_list[fragstrings_count++] = "\n";
1178                 }
1179         }
1180
1181         // add static parms
1182         R_CompileShader_AddStaticParms(mode, permutation);
1183         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184         vertstrings_count += shaderstaticparms_count;
1185         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186         geomstrings_count += shaderstaticparms_count;
1187         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1188         fragstrings_count += shaderstaticparms_count;
1189
1190         // now append the shader text itself
1191         vertstrings_list[vertstrings_count++] = sourcestring;
1192         geomstrings_list[geomstrings_count++] = sourcestring;
1193         fragstrings_list[fragstrings_count++] = sourcestring;
1194
1195         // compile the shader program
1196         if (vertstrings_count + geomstrings_count + fragstrings_count)
1197                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1198         if (p->program)
1199         {
1200                 CHECKGLERROR
1201                 qglUseProgram(p->program);CHECKGLERROR
1202                 // look up all the uniform variable names we care about, so we don't
1203                 // have to look them up every time we set them
1204
1205 #if 0
1206                 // debugging aid
1207                 {
1208                         GLint activeuniformindex = 0;
1209                         GLint numactiveuniforms = 0;
1210                         char uniformname[128];
1211                         GLsizei uniformnamelength = 0;
1212                         GLint uniformsize = 0;
1213                         GLenum uniformtype = 0;
1214                         memset(uniformname, 0, sizeof(uniformname));
1215                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1216                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1217                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1218                         {
1219                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1220                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1221                         }
1222                 }
1223 #endif
1224
1225                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1226                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1227                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1228                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1229                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1230                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1231                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1232                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1233                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1234                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1235                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1236                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1237                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1238                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1239                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1240                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1241                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1242                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1243                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1244                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1245                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1246                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1247                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1248                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1249                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1250                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1251                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1252                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1253                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1254                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1255                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1256                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1257                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1258                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1259                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1260                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1261                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1262                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1263                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1264                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1265                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1266                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1267                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1268                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1269                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1270                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1271                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1272                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1273                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1274                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1275                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1276                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1277                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1278                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1279                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1280                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1281                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1282                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1283                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1284                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1285                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1286                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1287                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1288                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1289                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1290                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1291                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1292                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1293                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1294                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1295                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1296                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1297                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1298                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1299                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1300                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1301                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1302                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1303                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1304                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1305                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1306                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1307                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1308                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1309                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1310                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1311                 // initialize the samplers to refer to the texture units we use
1312                 p->tex_Texture_First = -1;
1313                 p->tex_Texture_Second = -1;
1314                 p->tex_Texture_GammaRamps = -1;
1315                 p->tex_Texture_Normal = -1;
1316                 p->tex_Texture_Color = -1;
1317                 p->tex_Texture_Gloss = -1;
1318                 p->tex_Texture_Glow = -1;
1319                 p->tex_Texture_SecondaryNormal = -1;
1320                 p->tex_Texture_SecondaryColor = -1;
1321                 p->tex_Texture_SecondaryGloss = -1;
1322                 p->tex_Texture_SecondaryGlow = -1;
1323                 p->tex_Texture_Pants = -1;
1324                 p->tex_Texture_Shirt = -1;
1325                 p->tex_Texture_FogHeightTexture = -1;
1326                 p->tex_Texture_FogMask = -1;
1327                 p->tex_Texture_Lightmap = -1;
1328                 p->tex_Texture_Deluxemap = -1;
1329                 p->tex_Texture_Attenuation = -1;
1330                 p->tex_Texture_Cube = -1;
1331                 p->tex_Texture_Refraction = -1;
1332                 p->tex_Texture_Reflection = -1;
1333                 p->tex_Texture_ShadowMap2D = -1;
1334                 p->tex_Texture_CubeProjection = -1;
1335                 p->tex_Texture_ScreenNormalMap = -1;
1336                 p->tex_Texture_ScreenDiffuse = -1;
1337                 p->tex_Texture_ScreenSpecular = -1;
1338                 p->tex_Texture_ReflectMask = -1;
1339                 p->tex_Texture_ReflectCube = -1;
1340                 p->tex_Texture_BounceGrid = -1;
1341                 // bind the texture samplers in use
1342                 sampler = 0;
1343                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1344                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1345                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1346                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1347                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1348                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1349                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1352                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1353                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1354                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1355                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1356                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1357                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1358                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1359                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1360                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1361                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1362                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1363                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1364                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1365                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1367                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1368                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1369                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1370                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1371                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1372                 // get the uniform block indices so we can bind them
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374                 if (vid.support.arb_uniform_buffer_object)
1375                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1376                 else
1377 #endif
1378                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1379                 // clear the uniform block bindings
1380                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1381                 // bind the uniform blocks in use
1382                 ubibind = 0;
1383 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1384                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1385 #endif
1386                 // we're done compiling and setting up the shader, at least until it is used
1387                 CHECKGLERROR
1388                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1389         }
1390         else
1391                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1392
1393         // free the strings
1394         if (sourcestring)
1395                 Mem_Free(sourcestring);
1396 }
1397
1398 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1399 {
1400         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1401         if (r_glsl_permutation != perm)
1402         {
1403                 r_glsl_permutation = perm;
1404                 if (!r_glsl_permutation->program)
1405                 {
1406                         if (!r_glsl_permutation->compiled)
1407                         {
1408                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1409                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1410                         }
1411                         if (!r_glsl_permutation->program)
1412                         {
1413                                 // remove features until we find a valid permutation
1414                                 int i;
1415                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1416                                 {
1417                                         // reduce i more quickly whenever it would not remove any bits
1418                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1419                                         if (!(permutation & j))
1420                                                 continue;
1421                                         permutation -= j;
1422                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1423                                         if (!r_glsl_permutation->compiled)
1424                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1425                                         if (r_glsl_permutation->program)
1426                                                 break;
1427                                 }
1428                                 if (i >= SHADERPERMUTATION_COUNT)
1429                                 {
1430                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1431                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1432                                         qglUseProgram(0);CHECKGLERROR
1433                                         return; // no bit left to clear, entire mode is broken
1434                                 }
1435                         }
1436                 }
1437                 CHECKGLERROR
1438                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1439         }
1440         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1441         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1442         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1443         CHECKGLERROR
1444 }
1445
1446 #ifdef SUPPORTD3D
1447
1448 #ifdef SUPPORTD3D
1449 #include <d3d9.h>
1450 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1451 extern D3DCAPS9 vid_d3d9caps;
1452 #endif
1453
1454 struct r_hlsl_permutation_s;
1455 typedef struct r_hlsl_permutation_s
1456 {
1457         /// hash lookup data
1458         struct r_hlsl_permutation_s *hashnext;
1459         unsigned int mode;
1460         dpuint64 permutation;
1461
1462         /// indicates if we have tried compiling this permutation already
1463         qboolean compiled;
1464         /// NULL if compilation failed
1465         IDirect3DVertexShader9 *vertexshader;
1466         IDirect3DPixelShader9 *pixelshader;
1467 }
1468 r_hlsl_permutation_t;
1469
1470 typedef enum D3DVSREGISTER_e
1471 {
1472         D3DVSREGISTER_TexMatrix = 0, // float4x4
1473         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1474         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1475         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1476         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1477         D3DVSREGISTER_ModelToLight = 20, // float4x4
1478         D3DVSREGISTER_EyePosition = 24,
1479         D3DVSREGISTER_FogPlane = 25,
1480         D3DVSREGISTER_LightDir = 26,
1481         D3DVSREGISTER_LightPosition = 27,
1482 }
1483 D3DVSREGISTER_t;
1484
1485 typedef enum D3DPSREGISTER_e
1486 {
1487         D3DPSREGISTER_Alpha = 0,
1488         D3DPSREGISTER_BloomBlur_Parameters = 1,
1489         D3DPSREGISTER_ClientTime = 2,
1490         D3DPSREGISTER_Color_Ambient = 3,
1491         D3DPSREGISTER_Color_Diffuse = 4,
1492         D3DPSREGISTER_Color_Specular = 5,
1493         D3DPSREGISTER_Color_Glow = 6,
1494         D3DPSREGISTER_Color_Pants = 7,
1495         D3DPSREGISTER_Color_Shirt = 8,
1496         D3DPSREGISTER_DeferredColor_Ambient = 9,
1497         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1498         D3DPSREGISTER_DeferredColor_Specular = 11,
1499         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1500         D3DPSREGISTER_DeferredMod_Specular = 13,
1501         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1502         D3DPSREGISTER_EyePosition = 15, // unused
1503         D3DPSREGISTER_FogColor = 16,
1504         D3DPSREGISTER_FogHeightFade = 17,
1505         D3DPSREGISTER_FogPlane = 18,
1506         D3DPSREGISTER_FogPlaneViewDist = 19,
1507         D3DPSREGISTER_FogRangeRecip = 20,
1508         D3DPSREGISTER_LightColor = 21,
1509         D3DPSREGISTER_LightDir = 22, // unused
1510         D3DPSREGISTER_LightPosition = 23,
1511         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1512         D3DPSREGISTER_PixelSize = 25,
1513         D3DPSREGISTER_ReflectColor = 26,
1514         D3DPSREGISTER_ReflectFactor = 27,
1515         D3DPSREGISTER_ReflectOffset = 28,
1516         D3DPSREGISTER_RefractColor = 29,
1517         D3DPSREGISTER_Saturation = 30,
1518         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1519         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1520         D3DPSREGISTER_ScreenToDepth = 33,
1521         D3DPSREGISTER_ShadowMap_Parameters = 34,
1522         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1523         D3DPSREGISTER_SpecularPower = 36,
1524         D3DPSREGISTER_UserVec1 = 37,
1525         D3DPSREGISTER_UserVec2 = 38,
1526         D3DPSREGISTER_UserVec3 = 39,
1527         D3DPSREGISTER_UserVec4 = 40,
1528         D3DPSREGISTER_ViewTintColor = 41,
1529         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1530         D3DPSREGISTER_BloomColorSubtract = 43,
1531         D3DPSREGISTER_ViewToLight = 44, // float4x4
1532         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1533         D3DPSREGISTER_NormalmapScrollBlend = 52,
1534         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1535         D3DPSREGISTER_OffsetMapping_Bias = 54,
1536         // next at 54
1537 }
1538 D3DPSREGISTER_t;
1539
1540 /// information about each possible shader permutation
1541 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1542 /// currently selected permutation
1543 r_hlsl_permutation_t *r_hlsl_permutation;
1544 /// storage for permutations linked in the hash table
1545 memexpandablearray_t r_hlsl_permutationarray;
1546
1547 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1548 {
1549         //unsigned int hashdepth = 0;
1550         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1551         r_hlsl_permutation_t *p;
1552         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1553         {
1554                 if (p->mode == mode && p->permutation == permutation)
1555                 {
1556                         //if (hashdepth > 10)
1557                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1558                         return p;
1559                 }
1560                 //hashdepth++;
1561         }
1562         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1563         p->mode = mode;
1564         p->permutation = permutation;
1565         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1566         r_hlsl_permutationhash[mode][hashindex] = p;
1567         //if (hashdepth > 10)
1568         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1569         return p;
1570 }
1571
1572 #include <d3dx9.h>
1573 //#include <d3dx9shader.h>
1574 //#include <d3dx9mesh.h>
1575
1576 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1577 {
1578         DWORD *vsbin = NULL;
1579         DWORD *psbin = NULL;
1580         fs_offset_t vsbinsize;
1581         fs_offset_t psbinsize;
1582 //      IDirect3DVertexShader9 *vs = NULL;
1583 //      IDirect3DPixelShader9 *ps = NULL;
1584         ID3DXBuffer *vslog = NULL;
1585         ID3DXBuffer *vsbuffer = NULL;
1586         ID3DXConstantTable *vsconstanttable = NULL;
1587         ID3DXBuffer *pslog = NULL;
1588         ID3DXBuffer *psbuffer = NULL;
1589         ID3DXConstantTable *psconstanttable = NULL;
1590         int vsresult = 0;
1591         int psresult = 0;
1592         char temp[MAX_INPUTLINE];
1593         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1594         char vabuf[1024];
1595         qboolean debugshader = gl_paranoid.integer != 0;
1596         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1598         if (!debugshader)
1599         {
1600                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1601                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1602         }
1603         if ((!vsbin && vertstring) || (!psbin && fragstring))
1604         {
1605                 const char* dllnames_d3dx9 [] =
1606                 {
1607                         "d3dx9_43.dll",
1608                         "d3dx9_42.dll",
1609                         "d3dx9_41.dll",
1610                         "d3dx9_40.dll",
1611                         "d3dx9_39.dll",
1612                         "d3dx9_38.dll",
1613                         "d3dx9_37.dll",
1614                         "d3dx9_36.dll",
1615                         "d3dx9_35.dll",
1616                         "d3dx9_34.dll",
1617                         "d3dx9_33.dll",
1618                         "d3dx9_32.dll",
1619                         "d3dx9_31.dll",
1620                         "d3dx9_30.dll",
1621                         "d3dx9_29.dll",
1622                         "d3dx9_28.dll",
1623                         "d3dx9_27.dll",
1624                         "d3dx9_26.dll",
1625                         "d3dx9_25.dll",
1626                         "d3dx9_24.dll",
1627                         NULL
1628                 };
1629                 dllhandle_t d3dx9_dll = NULL;
1630                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1632                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1633                 dllfunction_t d3dx9_dllfuncs[] =
1634                 {
1635                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1636                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1637                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1638                         {NULL, NULL}
1639                 };
1640                 // 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...
1641 #ifndef ID3DXBuffer_GetBufferPointer
1642 #if !defined(__cplusplus) || defined(CINTERFACE)
1643 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1644 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1645 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1646 #else
1647 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1648 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1649 #define ID3DXBuffer_Release(p)            (p)->Release()
1650 #endif
1651 #endif
1652                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1653                 {
1654                         DWORD shaderflags = 0;
1655                         if (debugshader)
1656                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1657                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1658                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1659                         if (vertstring && vertstring[0])
1660                         {
1661                                 if (debugshader)
1662                                 {
1663                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1664                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1665                                 }
1666                                 else
1667                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1668                                 if (vsbuffer)
1669                                 {
1670                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1671                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1672                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1673                                         ID3DXBuffer_Release(vsbuffer);
1674                                 }
1675                                 if (vslog)
1676                                 {
1677                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1678                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1679                                         ID3DXBuffer_Release(vslog);
1680                                 }
1681                         }
1682                         if (fragstring && fragstring[0])
1683                         {
1684                                 if (debugshader)
1685                                 {
1686                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1687                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1688                                 }
1689                                 else
1690                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1691                                 if (psbuffer)
1692                                 {
1693                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1694                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1695                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1696                                         ID3DXBuffer_Release(psbuffer);
1697                                 }
1698                                 if (pslog)
1699                                 {
1700                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1701                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1702                                         ID3DXBuffer_Release(pslog);
1703                                 }
1704                         }
1705                         Sys_UnloadLibrary(&d3dx9_dll);
1706                 }
1707                 else
1708                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1709         }
1710         if (vsbin && psbin)
1711         {
1712                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1713                 if (FAILED(vsresult))
1714                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1715                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1716                 if (FAILED(psresult))
1717                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1718         }
1719         // free the shader data
1720         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1721         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1722 }
1723
1724 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1725 {
1726         int i;
1727         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1728         int vertstring_length = 0;
1729         int geomstring_length = 0;
1730         int fragstring_length = 0;
1731         char *t;
1732         char *sourcestring;
1733         char *vertstring, *geomstring, *fragstring;
1734         char permutationname[256];
1735         char cachename[256];
1736         int vertstrings_count = 0;
1737         int geomstrings_count = 0;
1738         int fragstrings_count = 0;
1739         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1742
1743         if (p->compiled)
1744                 return;
1745         p->compiled = true;
1746         p->vertexshader = NULL;
1747         p->pixelshader = NULL;
1748
1749         permutationname[0] = 0;
1750         cachename[0] = 0;
1751         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1752
1753         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1754         strlcat(cachename, "hlsl/", sizeof(cachename));
1755
1756         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1757         vertstrings_count = 0;
1758         geomstrings_count = 0;
1759         fragstrings_count = 0;
1760         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1761         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1762         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1763
1764         // the first pretext is which type of shader to compile as
1765         // (later these will all be bound together as a program object)
1766         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1767         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1768         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1769
1770         // the second pretext is the mode (for example a light source)
1771         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1772         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1773         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1774         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1775         strlcat(cachename, modeinfo->name, sizeof(cachename));
1776
1777         // now add all the permutation pretexts
1778         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779         {
1780                 if (permutation & (1ll<<i))
1781                 {
1782                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1784                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1785                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1786                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1787                 }
1788                 else
1789                 {
1790                         // keep line numbers correct
1791                         vertstrings_list[vertstrings_count++] = "\n";
1792                         geomstrings_list[geomstrings_count++] = "\n";
1793                         fragstrings_list[fragstrings_count++] = "\n";
1794                 }
1795         }
1796
1797         // add static parms
1798         R_CompileShader_AddStaticParms(mode, permutation);
1799         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800         vertstrings_count += shaderstaticparms_count;
1801         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802         geomstrings_count += shaderstaticparms_count;
1803         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1804         fragstrings_count += shaderstaticparms_count;
1805
1806         // replace spaces in the cachename with _ characters
1807         for (i = 0;cachename[i];i++)
1808                 if (cachename[i] == ' ')
1809                         cachename[i] = '_';
1810
1811         // now append the shader text itself
1812         vertstrings_list[vertstrings_count++] = sourcestring;
1813         geomstrings_list[geomstrings_count++] = sourcestring;
1814         fragstrings_list[fragstrings_count++] = sourcestring;
1815
1816         vertstring_length = 0;
1817         for (i = 0;i < vertstrings_count;i++)
1818                 vertstring_length += (int)strlen(vertstrings_list[i]);
1819         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1820         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1821                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1822
1823         geomstring_length = 0;
1824         for (i = 0;i < geomstrings_count;i++)
1825                 geomstring_length += (int)strlen(geomstrings_list[i]);
1826         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1827         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1828                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1829
1830         fragstring_length = 0;
1831         for (i = 0;i < fragstrings_count;i++)
1832                 fragstring_length += (int)strlen(fragstrings_list[i]);
1833         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1834         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1835                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1836
1837         // try to load the cached shader, or generate one
1838         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1839
1840         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1841                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1842         else
1843                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1844
1845         // free the strings
1846         if (vertstring)
1847                 Mem_Free(vertstring);
1848         if (geomstring)
1849                 Mem_Free(geomstring);
1850         if (fragstring)
1851                 Mem_Free(fragstring);
1852         if (sourcestring)
1853                 Mem_Free(sourcestring);
1854 }
1855
1856 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1857 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1858 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);}
1859 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);}
1860 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);}
1861 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);}
1862
1863 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1864 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1865 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);}
1866 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);}
1867 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);}
1868 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);}
1869
1870 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1871 {
1872         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1873         if (r_hlsl_permutation != perm)
1874         {
1875                 r_hlsl_permutation = perm;
1876                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1877                 {
1878                         if (!r_hlsl_permutation->compiled)
1879                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1880                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1881                         {
1882                                 // remove features until we find a valid permutation
1883                                 int i;
1884                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885                                 {
1886                                         // reduce i more quickly whenever it would not remove any bits
1887                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1888                                         if (!(permutation & j))
1889                                                 continue;
1890                                         permutation -= j;
1891                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1892                                         if (!r_hlsl_permutation->compiled)
1893                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1894                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1895                                                 break;
1896                                 }
1897                                 if (i >= SHADERPERMUTATION_COUNT)
1898                                 {
1899                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1900                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1901                                         return; // no bit left to clear, entire mode is broken
1902                                 }
1903                         }
1904                 }
1905                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1906                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1907         }
1908         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1909         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1910         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1911 }
1912 #endif
1913
1914 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1915 {
1916         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1917         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1918         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1919         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1920 }
1921
1922 void R_GLSL_Restart_f(void)
1923 {
1924         unsigned int i, limit;
1925         switch(vid.renderpath)
1926         {
1927         case RENDERPATH_D3D9:
1928 #ifdef SUPPORTD3D
1929                 {
1930                         r_hlsl_permutation_t *p;
1931                         r_hlsl_permutation = NULL;
1932                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1933                         for (i = 0;i < limit;i++)
1934                         {
1935                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1936                                 {
1937                                         if (p->vertexshader)
1938                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1939                                         if (p->pixelshader)
1940                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1941                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1942                                 }
1943                         }
1944                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1945                 }
1946 #endif
1947                 break;
1948         case RENDERPATH_D3D10:
1949                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950                 break;
1951         case RENDERPATH_D3D11:
1952                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953                 break;
1954         case RENDERPATH_GL20:
1955         case RENDERPATH_GLES2:
1956                 {
1957                         r_glsl_permutation_t *p;
1958                         r_glsl_permutation = NULL;
1959                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1960                         for (i = 0;i < limit;i++)
1961                         {
1962                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1963                                 {
1964                                         GL_Backend_FreeProgram(p->program);
1965                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1966                                 }
1967                         }
1968                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1969                 }
1970                 break;
1971         case RENDERPATH_GL11:
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 break;
1977         }
1978 }
1979
1980 static void R_GLSL_DumpShader_f(void)
1981 {
1982         int i, language, mode, dupe;
1983         char *text;
1984         shadermodeinfo_t *modeinfo;
1985         qfile_t *file;
1986
1987         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1988         {
1989                 modeinfo = shadermodeinfo[language];
1990                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1991                 {
1992                         // don't dump the same file multiple times (most or all shaders come from the same file)
1993                         for (dupe = mode - 1;dupe >= 0;dupe--)
1994                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1995                                         break;
1996                         if (dupe >= 0)
1997                                 continue;
1998                         text = modeinfo[mode].builtinstring;
1999                         if (!text)
2000                                 continue;
2001                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2002                         if (file)
2003                         {
2004                                 FS_Print(file, "/* The engine may define the following macros:\n");
2005                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2006                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2007                                         FS_Print(file, modeinfo[i].pretext);
2008                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2009                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2010                                 FS_Print(file, "*/\n");
2011                                 FS_Print(file, text);
2012                                 FS_Close(file);
2013                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2014                         }
2015                         else
2016                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2017                 }
2018         }
2019 }
2020
2021 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2022 {
2023         dpuint64 permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         permutation |= SHADERPERMUTATION_VIEWTINT;
2027         if (first)
2028                 permutation |= SHADERPERMUTATION_DIFFUSE;
2029         if (second)
2030                 permutation |= SHADERPERMUTATION_SPECULAR;
2031         if (texturemode == GL_MODULATE)
2032                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2033         else if (texturemode == GL_ADD)
2034                 permutation |= SHADERPERMUTATION_GLOW;
2035         else if (texturemode == GL_DECAL)
2036                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2037         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2038                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2039         if (suppresstexalpha)
2040                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2041         if (!second)
2042                 texturemode = GL_MODULATE;
2043         if (vid.allowalphatocoverage)
2044                 GL_AlphaToCoverage(false);
2045         switch (vid.renderpath)
2046         {
2047         case RENDERPATH_D3D9:
2048 #ifdef SUPPORTD3D
2049                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2050                 R_Mesh_TexBind(GL20TU_FIRST , first );
2051                 R_Mesh_TexBind(GL20TU_SECOND, second);
2052                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2054 #endif
2055                 break;
2056         case RENDERPATH_D3D10:
2057                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2058                 break;
2059         case RENDERPATH_D3D11:
2060                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061                 break;
2062         case RENDERPATH_GL20:
2063         case RENDERPATH_GLES2:
2064                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2065                 if (r_glsl_permutation->tex_Texture_First >= 0)
2066                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2067                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2068                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2069                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2070                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2071                 break;
2072         case RENDERPATH_GL13:
2073         case RENDERPATH_GLES1:
2074                 R_Mesh_TexBind(0, first );
2075                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2076                 R_Mesh_TexMatrix(0, NULL);
2077                 R_Mesh_TexBind(1, second);
2078                 if (second)
2079                 {
2080                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2081                         R_Mesh_TexMatrix(1, NULL);
2082                 }
2083                 break;
2084         case RENDERPATH_GL11:
2085                 R_Mesh_TexBind(0, first );
2086                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2087                 R_Mesh_TexMatrix(0, NULL);
2088                 break;
2089         case RENDERPATH_SOFT:
2090                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2091                 R_Mesh_TexBind(GL20TU_FIRST , first );
2092                 R_Mesh_TexBind(GL20TU_SECOND, second);
2093                 break;
2094         }
2095 }
2096
2097 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2098 {
2099         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2100 }
2101
2102 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2103 {
2104         dpuint64 permutation = 0;
2105         if (r_trippy.integer && !notrippy)
2106                 permutation |= SHADERPERMUTATION_TRIPPY;
2107         if (depthrgb)
2108                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2109         if (skeletal)
2110                 permutation |= SHADERPERMUTATION_SKELETAL;
2111
2112         if (vid.allowalphatocoverage)
2113                 GL_AlphaToCoverage(false);
2114         switch (vid.renderpath)
2115         {
2116         case RENDERPATH_D3D9:
2117 #ifdef SUPPORTD3D
2118                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2119 #endif
2120                 break;
2121         case RENDERPATH_D3D10:
2122                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2123                 break;
2124         case RENDERPATH_D3D11:
2125                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2126                 break;
2127         case RENDERPATH_GL20:
2128         case RENDERPATH_GLES2:
2129                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2130 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2131                 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);
2132 #endif
2133                 break;
2134         case RENDERPATH_GL13:
2135         case RENDERPATH_GLES1:
2136                 R_Mesh_TexBind(0, 0);
2137                 R_Mesh_TexBind(1, 0);
2138                 break;
2139         case RENDERPATH_GL11:
2140                 R_Mesh_TexBind(0, 0);
2141                 break;
2142         case RENDERPATH_SOFT:
2143                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2144                 break;
2145         }
2146 }
2147
2148 extern qboolean r_shadow_usingdeferredprepass;
2149 extern rtexture_t *r_shadow_attenuationgradienttexture;
2150 extern rtexture_t *r_shadow_attenuation2dtexture;
2151 extern rtexture_t *r_shadow_attenuation3dtexture;
2152 extern qboolean r_shadow_usingshadowmap2d;
2153 extern qboolean r_shadow_usingshadowmaportho;
2154 extern float r_shadow_modelshadowmap_texturescale[4];
2155 extern float r_shadow_modelshadowmap_parameters[4];
2156 extern float r_shadow_lightshadowmap_texturescale[4];
2157 extern float r_shadow_lightshadowmap_parameters[4];
2158 extern qboolean r_shadow_shadowmapvsdct;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2160 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2161 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2162 extern matrix4x4_t r_shadow_shadowmapmatrix;
2163 extern int r_shadow_prepass_width;
2164 extern int r_shadow_prepass_height;
2165 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2166 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2167 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2168 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2169
2170 #define BLENDFUNC_ALLOWS_COLORMOD      1
2171 #define BLENDFUNC_ALLOWS_FOG           2
2172 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2173 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2174 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2175 static int R_BlendFuncFlags(int src, int dst)
2176 {
2177         int r = 0;
2178
2179         // a blendfunc allows colormod if:
2180         // a) it can never keep the destination pixel invariant, or
2181         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2182         // this is to prevent unintended side effects from colormod
2183
2184         // a blendfunc allows fog if:
2185         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2186         // this is to prevent unintended side effects from fog
2187
2188         // these checks are the output of fogeval.pl
2189
2190         r |= BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2200         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2201         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2202         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2205         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2206         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2208         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2209         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2210         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2211         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2212
2213         return r;
2214 }
2215
2216 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)
2217 {
2218         // select a permutation of the lighting shader appropriate to this
2219         // combination of texture, entity, light source, and fogging, only use the
2220         // minimum features necessary to avoid wasting rendering time in the
2221         // fragment shader on features that are not being used
2222         dpuint64 permutation = 0;
2223         unsigned int mode = 0;
2224         int blendfuncflags;
2225         static float dummy_colormod[3] = {1, 1, 1};
2226         float *colormod = rsurface.colormod;
2227         float m16f[16];
2228         matrix4x4_t tempmatrix;
2229         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2230         if (r_trippy.integer && !notrippy)
2231                 permutation |= SHADERPERMUTATION_TRIPPY;
2232         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2233                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2234         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2235                 permutation |= SHADERPERMUTATION_OCCLUDE;
2236         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2237                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2238         if (rsurfacepass == RSURFPASS_BACKGROUND)
2239         {
2240                 // distorted background
2241                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2242                 {
2243                         mode = SHADERMODE_WATER;
2244                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2245                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2246                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2247                         {
2248                                 // this is the right thing to do for wateralpha
2249                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2250                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2251                         }
2252                         else
2253                         {
2254                                 // this is the right thing to do for entity alpha
2255                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257                         }
2258                 }
2259                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2260                 {
2261                         mode = SHADERMODE_REFRACTION;
2262                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2263                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2264                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266                 }
2267                 else
2268                 {
2269                         mode = SHADERMODE_GENERIC;
2270                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2271                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2272                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2273                 }
2274                 if (vid.allowalphatocoverage)
2275                         GL_AlphaToCoverage(false);
2276         }
2277         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2278         {
2279                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 // normalmap (deferred prepass), may use alpha test on diffuse
2292                 mode = SHADERMODE_DEFERREDGEOMETRY;
2293                 GL_BlendFunc(GL_ONE, GL_ZERO);
2294                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2295                 if (vid.allowalphatocoverage)
2296                         GL_AlphaToCoverage(false);
2297         }
2298         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2299         {
2300                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2301                 {
2302                         switch(rsurface.texture->offsetmapping)
2303                         {
2304                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2305                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2307                         case OFFSETMAPPING_OFF: break;
2308                         }
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2311                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2313                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2314                 // light source
2315                 mode = SHADERMODE_LIGHTSOURCE;
2316                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2317                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2318                 if (diffusescale > 0)
2319                         permutation |= SHADERPERMUTATION_DIFFUSE;
2320                 if (specularscale > 0)
2321                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2322                 if (r_refdef.fogenabled)
2323                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2324                 if (rsurface.texture->colormapping)
2325                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2326                 if (r_shadow_usingshadowmap2d)
2327                 {
2328                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329                         if(r_shadow_shadowmapvsdct)
2330                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2331
2332                         if (r_shadow_shadowmap2ddepthbuffer)
2333                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2334                 }
2335                 if (rsurface.texture->reflectmasktexture)
2336                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2337                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2338                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2339                 if (vid.allowalphatocoverage)
2340                         GL_AlphaToCoverage(false);
2341         }
2342         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2343         {
2344                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2345                 {
2346                         switch(rsurface.texture->offsetmapping)
2347                         {
2348                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_OFF: break;
2352                         }
2353                 }
2354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2357                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2358                 // unshaded geometry (fullbright or ambient model lighting)
2359                 mode = SHADERMODE_FLATCOLOR;
2360                 ambientscale = diffusescale = specularscale = 0;
2361                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362                         permutation |= SHADERPERMUTATION_GLOW;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (rsurface.texture->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmap2ddepthbuffer)
2373                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (rsurface.texture->reflectmasktexture)
2378                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2379                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2380                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2381                 // when using alphatocoverage, we don't need alphakill
2382                 if (vid.allowalphatocoverage)
2383                 {
2384                         if (r_transparent_alphatocoverage.integer)
2385                         {
2386                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2387                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2388                         }
2389                         else
2390                                 GL_AlphaToCoverage(false);
2391                 }
2392         }
2393         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2394         {
2395                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2396                 {
2397                         switch(rsurface.texture->offsetmapping)
2398                         {
2399                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2400                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2401                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2402                         case OFFSETMAPPING_OFF: break;
2403                         }
2404                 }
2405                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2406                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2408                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2409                 // directional model lighting
2410                 mode = SHADERMODE_LIGHTDIRECTION;
2411                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2412                         permutation |= SHADERPERMUTATION_GLOW;
2413                 permutation |= SHADERPERMUTATION_DIFFUSE;
2414                 if (specularscale > 0)
2415                         permutation |= SHADERPERMUTATION_SPECULAR;
2416                 if (r_refdef.fogenabled)
2417                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2418                 if (rsurface.texture->colormapping)
2419                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2420                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2421                 {
2422                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2423                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2424
2425                         if (r_shadow_shadowmap2ddepthbuffer)
2426                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2427                 }
2428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2429                         permutation |= SHADERPERMUTATION_REFLECTION;
2430                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2431                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2432                 if (rsurface.texture->reflectmasktexture)
2433                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2434                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2435                 {
2436                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2437                         if (r_shadow_bouncegrid_state.directional)
2438                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2439                 }
2440                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2441                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2442                 // when using alphatocoverage, we don't need alphakill
2443                 if (vid.allowalphatocoverage)
2444                 {
2445                         if (r_transparent_alphatocoverage.integer)
2446                         {
2447                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2448                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2449                         }
2450                         else
2451                                 GL_AlphaToCoverage(false);
2452                 }
2453         }
2454         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2455         {
2456                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2457                 {
2458                         switch(rsurface.texture->offsetmapping)
2459                         {
2460                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2461                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2462                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2463                         case OFFSETMAPPING_OFF: break;
2464                         }
2465                 }
2466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2467                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2469                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2470                 // ambient model lighting
2471                 mode = SHADERMODE_LIGHTDIRECTION;
2472                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2473                         permutation |= SHADERPERMUTATION_GLOW;
2474                 if (r_refdef.fogenabled)
2475                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2476                 if (rsurface.texture->colormapping)
2477                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2478                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2479                 {
2480                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2481                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2482
2483                         if (r_shadow_shadowmap2ddepthbuffer)
2484                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2485                 }
2486                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2487                         permutation |= SHADERPERMUTATION_REFLECTION;
2488                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2489                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2490                 if (rsurface.texture->reflectmasktexture)
2491                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2492                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2493                 {
2494                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2495                         if (r_shadow_bouncegrid_state.directional)
2496                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2497                 }
2498                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2499                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2500                 // when using alphatocoverage, we don't need alphakill
2501                 if (vid.allowalphatocoverage)
2502                 {
2503                         if (r_transparent_alphatocoverage.integer)
2504                         {
2505                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2506                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2507                         }
2508                         else
2509                                 GL_AlphaToCoverage(false);
2510                 }
2511         }
2512         else
2513         {
2514                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2515                 {
2516                         switch(rsurface.texture->offsetmapping)
2517                         {
2518                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2519                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2520                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2521                         case OFFSETMAPPING_OFF: break;
2522                         }
2523                 }
2524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2525                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2527                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2528                 // lightmapped wall
2529                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2530                         permutation |= SHADERPERMUTATION_GLOW;
2531                 if (r_refdef.fogenabled)
2532                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2533                 if (rsurface.texture->colormapping)
2534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2535                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2536                 {
2537                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2538                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2539
2540                         if (r_shadow_shadowmap2ddepthbuffer)
2541                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2542                 }
2543                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2544                         permutation |= SHADERPERMUTATION_REFLECTION;
2545                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2546                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2547                 if (rsurface.texture->reflectmasktexture)
2548                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2549                 if (FAKELIGHT_ENABLED)
2550                 {
2551                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2552                         mode = SHADERMODE_FAKELIGHT;
2553                         permutation |= SHADERPERMUTATION_DIFFUSE;
2554                         if (specularscale > 0)
2555                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2556                 }
2557                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2558                 {
2559                         // deluxemapping (light direction texture)
2560                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2561                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2562                         else
2563                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2564                         permutation |= SHADERPERMUTATION_DIFFUSE;
2565                         if (specularscale > 0)
2566                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2567                 }
2568                 else if (r_glsl_deluxemapping.integer >= 2)
2569                 {
2570                         // fake deluxemapping (uniform light direction in tangentspace)
2571                         if (rsurface.uselightmaptexture)
2572                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2573                         else
2574                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2575                         permutation |= SHADERPERMUTATION_DIFFUSE;
2576                         if (specularscale > 0)
2577                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2578                 }
2579                 else if (rsurface.uselightmaptexture)
2580                 {
2581                         // ordinary lightmapping (q1bsp, q3bsp)
2582                         mode = SHADERMODE_LIGHTMAP;
2583                 }
2584                 else
2585                 {
2586                         // ordinary vertex coloring (q3bsp)
2587                         mode = SHADERMODE_VERTEXCOLOR;
2588                 }
2589                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2590                 {
2591                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2592                         if (r_shadow_bouncegrid_state.directional)
2593                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2594                 }
2595                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2596                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2597                 // when using alphatocoverage, we don't need alphakill
2598                 if (vid.allowalphatocoverage)
2599                 {
2600                         if (r_transparent_alphatocoverage.integer)
2601                         {
2602                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2603                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2604                         }
2605                         else
2606                                 GL_AlphaToCoverage(false);
2607                 }
2608         }
2609         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2610                 colormod = dummy_colormod;
2611         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2612                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2613         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2614                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2615         switch(vid.renderpath)
2616         {
2617         case RENDERPATH_D3D9:
2618 #ifdef SUPPORTD3D
2619                 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);
2620                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2621                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2622                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2623                 if (mode == SHADERMODE_LIGHTSOURCE)
2624                 {
2625                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2626                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2627                 }
2628                 else
2629                 {
2630                         if (mode == SHADERMODE_LIGHTDIRECTION)
2631                         {
2632                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2633                         }
2634                 }
2635                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2636                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2637                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2638                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2639                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2640
2641                 if (mode == SHADERMODE_LIGHTSOURCE)
2642                 {
2643                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2644                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2645                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2646                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2647                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2648
2649                         // additive passes are only darkened by fog, not tinted
2650                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2651                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2652                 }
2653                 else
2654                 {
2655                         if (mode == SHADERMODE_FLATCOLOR)
2656                         {
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2658                         }
2659                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2660                         {
2661                                 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]);
2662                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2663                                 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);
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2666                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2667                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2668                         }
2669                         else
2670                         {
2671                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2672                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2673                                 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);
2674                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2675                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2676                         }
2677                         // additive passes are only darkened by fog, not tinted
2678                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2679                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2680                         else
2681                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2682                         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);
2683                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2684                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2685                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2686                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2687                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2688                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2689                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2690                         if (mode == SHADERMODE_WATER)
2691                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2692                 }
2693                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2694                 {
2695                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2696                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2697                 }
2698                 else
2699                 {
2700                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2701                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2702                 }
2703                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2704                 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));
2705                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2706                 if (rsurface.texture->pantstexture)
2707                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2708                 else
2709                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2710                 if (rsurface.texture->shirttexture)
2711                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2712                 else
2713                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2714                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2715                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2716                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2717                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2718                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2719                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2720                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2721                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2722                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2723                         );
2724                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2725                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2726                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2727                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2728
2729                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2730                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2731                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2732                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2733                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2734                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2735                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2736                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2737                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2738                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2739                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2740                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2741                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2742                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2743                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2744                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2745                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2746                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2747                 {
2748                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2749                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2750                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2751                 }
2752                 else
2753                 {
2754                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2755                 }
2756 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2757                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2758                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2759                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2760                 {
2761                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2762                         if (rsurface.rtlight)
2763                         {
2764                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2765                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2766                         }
2767                 }
2768 #endif
2769                 break;
2770         case RENDERPATH_D3D10:
2771                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2772                 break;
2773         case RENDERPATH_D3D11:
2774                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2775                 break;
2776         case RENDERPATH_GL20:
2777         case RENDERPATH_GLES2:
2778                 if (!vid.useinterleavedarrays)
2779                 {
2780                         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);
2781                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2782                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2783                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2784                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2785                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2786                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2787                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2788                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2789                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2790                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2791                 }
2792                 else
2793                 {
2794                         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);
2795                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2796                 }
2797                 // this has to be after RSurf_PrepareVerticesForBatch
2798                 if (rsurface.batchskeletaltransform3x4buffer)
2799                         permutation |= SHADERPERMUTATION_SKELETAL;
2800                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2801 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2802                 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);
2803 #endif
2804                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2805                 if (mode == SHADERMODE_LIGHTSOURCE)
2806                 {
2807                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2808                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2809                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2810                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2811                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2812                         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);
2813         
2814                         // additive passes are only darkened by fog, not tinted
2815                         if (r_glsl_permutation->loc_FogColor >= 0)
2816                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2817                         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);
2818                 }
2819                 else
2820                 {
2821                         if (mode == SHADERMODE_FLATCOLOR)
2822                         {
2823                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2824                         }
2825                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2826                         {
2827                                 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]);
2828                                 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]);
2829                                 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);
2830                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2831                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2832                                 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]);
2833                                 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]);
2834                         }
2835                         else
2836                         {
2837                                 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]);
2838                                 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]);
2839                                 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);
2840                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2841                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2842                         }
2843                         // additive passes are only darkened by fog, not tinted
2844                         if (r_glsl_permutation->loc_FogColor >= 0)
2845                         {
2846                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2847                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2848                                 else
2849                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2850                         }
2851                         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);
2852                         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]);
2853                         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]);
2854                         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]);
2855                         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]);
2856                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2857                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2858                         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);
2859                         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]);
2860                 }
2861                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2862                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2863                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2864                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2865                 {
2866                         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]);
2867                         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]);
2868                 }
2869                 else
2870                 {
2871                         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]);
2872                         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]);
2873                 }
2874
2875                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2876                 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));
2877                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2878                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2879                 {
2880                         if (rsurface.texture->pantstexture)
2881                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2882                         else
2883                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2884                 }
2885                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2886                 {
2887                         if (rsurface.texture->shirttexture)
2888                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2889                         else
2890                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2891                 }
2892                 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]);
2893                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2894                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2895                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2896                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2897                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2898                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2899                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2900                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2901                         );
2902                 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);
2903                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2904                 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]);
2905                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2906                 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);}
2907                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2908
2909                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2910                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2911                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2912                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2913                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2914                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2915                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2916                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2917                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2918                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2919                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2920                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2921                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2922                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2923                 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);
2924                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2925                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2926                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2927                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2928                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2929                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2930                 {
2931                         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);
2932                         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);
2933                         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);
2934                 }
2935                 else
2936                 {
2937                         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);
2938                 }
2939                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2940                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2941                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2942                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2943                 {
2944                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2945                         if (rsurface.rtlight)
2946                         {
2947                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2948                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2949                         }
2950                 }
2951                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2952                 CHECKGLERROR
2953                 break;
2954         case RENDERPATH_GL11:
2955         case RENDERPATH_GL13:
2956         case RENDERPATH_GLES1:
2957                 break;
2958         case RENDERPATH_SOFT:
2959                 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);
2960                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2961                 R_SetupShader_SetPermutationSoft(mode, permutation);
2962                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2963                 if (mode == SHADERMODE_LIGHTSOURCE)
2964                 {
2965                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2966                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2967                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2968                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2969                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2970                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2971         
2972                         // additive passes are only darkened by fog, not tinted
2973                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2974                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2975                 }
2976                 else
2977                 {
2978                         if (mode == SHADERMODE_FLATCOLOR)
2979                         {
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2981                         }
2982                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2983                         {
2984                                 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]);
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2986                                 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);
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2989                                 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]);
2990                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2991                         }
2992                         else
2993                         {
2994                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2995                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2996                                 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);
2997                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2998                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2999                         }
3000                         // additive passes are only darkened by fog, not tinted
3001                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
3002                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
3003                         else
3004                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3005                         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);
3006                         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]);
3007                         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]);
3008                         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]);
3009                         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]);
3010                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3011                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3012                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3013                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3014                 }
3015                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3016                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3017                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3018                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3019                 {
3020                         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]);
3021                         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]);
3022                 }
3023                 else
3024                 {
3025                         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]);
3026                         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]);
3027                 }
3028
3029                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3030                 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));
3031                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3032                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3033                 {
3034                         if (rsurface.texture->pantstexture)
3035                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3036                         else
3037                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3038                 }
3039                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3040                 {
3041                         if (rsurface.texture->shirttexture)
3042                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3043                         else
3044                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3045                 }
3046                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3047                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3048                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3049                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3050                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3051                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3052                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3053                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3054                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3055                         );
3056                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3057                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3058                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3059                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3060
3061                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3062                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3063                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3064                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3065                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3066                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3067                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3068                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3069                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3070                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3071                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3072                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3073                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3074                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3075                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3076                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3077                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3078                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3079                 {
3080                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3081                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3082                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3083                 }
3084                 else
3085                 {
3086                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3087                 }
3088 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3089                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3090                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3091                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3092                 {
3093                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3094                         if (rsurface.rtlight)
3095                         {
3096                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3097                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3098                         }
3099                 }
3100                 break;
3101         }
3102 }
3103
3104 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3105 {
3106         // select a permutation of the lighting shader appropriate to this
3107         // combination of texture, entity, light source, and fogging, only use the
3108         // minimum features necessary to avoid wasting rendering time in the
3109         // fragment shader on features that are not being used
3110         dpuint64 permutation = 0;
3111         unsigned int mode = 0;
3112         const float *lightcolorbase = rtlight->currentcolor;
3113         float ambientscale = rtlight->ambientscale;
3114         float diffusescale = rtlight->diffusescale;
3115         float specularscale = rtlight->specularscale;
3116         // this is the location of the light in view space
3117         vec3_t viewlightorigin;
3118         // this transforms from view space (camera) to light space (cubemap)
3119         matrix4x4_t viewtolight;
3120         matrix4x4_t lighttoview;
3121         float viewtolight16f[16];
3122         // light source
3123         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3124         if (rtlight->currentcubemap != r_texture_whitecube)
3125                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3126         if (diffusescale > 0)
3127                 permutation |= SHADERPERMUTATION_DIFFUSE;
3128         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3129                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3130         if (r_shadow_usingshadowmap2d)
3131         {
3132                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3133                 if (r_shadow_shadowmapvsdct)
3134                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3135
3136                 if (r_shadow_shadowmap2ddepthbuffer)
3137                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3138         }
3139         if (vid.allowalphatocoverage)
3140                 GL_AlphaToCoverage(false);
3141         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3142         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3143         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3144         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3145         switch(vid.renderpath)
3146         {
3147         case RENDERPATH_D3D9:
3148 #ifdef SUPPORTD3D
3149                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3150                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3151                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3152                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3153                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3154                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3155                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3156                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3157                 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);
3158                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3159                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3160
3161                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3162                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3163                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3164                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3165                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3166 #endif
3167                 break;
3168         case RENDERPATH_D3D10:
3169                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3170                 break;
3171         case RENDERPATH_D3D11:
3172                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3173                 break;
3174         case RENDERPATH_GL20:
3175         case RENDERPATH_GLES2:
3176                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3177                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3178                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3179                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3180                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3181                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3182                 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]);
3183                 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]);
3184                 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);
3185                 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]);
3186                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3187
3188                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3189                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3190                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3191                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3192                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3193                 break;
3194         case RENDERPATH_GL11:
3195         case RENDERPATH_GL13:
3196         case RENDERPATH_GLES1:
3197                 break;
3198         case RENDERPATH_SOFT:
3199                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3200                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3201                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3202                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3203                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3204                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3205                 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]);
3206                 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]);
3207                 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);
3208                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3209                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3210
3211                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3212                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3213                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3214                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3215                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3216                 break;
3217         }
3218 }
3219
3220 #define SKINFRAME_HASH 1024
3221
3222 typedef struct
3223 {
3224         unsigned int loadsequence; // incremented each level change
3225         memexpandablearray_t array;
3226         skinframe_t *hash[SKINFRAME_HASH];
3227 }
3228 r_skinframe_t;
3229 r_skinframe_t r_skinframe;
3230
3231 void R_SkinFrame_PrepareForPurge(void)
3232 {
3233         r_skinframe.loadsequence++;
3234         // wrap it without hitting zero
3235         if (r_skinframe.loadsequence >= 200)
3236                 r_skinframe.loadsequence = 1;
3237 }
3238
3239 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3240 {
3241         if (!skinframe)
3242                 return;
3243         // mark the skinframe as used for the purging code
3244         skinframe->loadsequence = r_skinframe.loadsequence;
3245 }
3246
3247 void R_SkinFrame_Purge(void)
3248 {
3249         int i;
3250         skinframe_t *s;
3251         for (i = 0;i < SKINFRAME_HASH;i++)
3252         {
3253                 for (s = r_skinframe.hash[i];s;s = s->next)
3254                 {
3255                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3256                         {
3257                                 if (s->merged == s->base)
3258                                         s->merged = NULL;
3259                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3260                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3261                                 R_PurgeTexture(s->merged);s->merged = NULL;
3262                                 R_PurgeTexture(s->base  );s->base   = NULL;
3263                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3264                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3265                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3266                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3267                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3268                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3269                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3270                                 s->loadsequence = 0;
3271                         }
3272                 }
3273         }
3274 }
3275
3276 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3277         skinframe_t *item;
3278         char basename[MAX_QPATH];
3279
3280         Image_StripImageExtension(name, basename, sizeof(basename));
3281
3282         if( last == NULL ) {
3283                 int hashindex;
3284                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3285                 item = r_skinframe.hash[hashindex];
3286         } else {
3287                 item = last->next;
3288         }
3289
3290         // linearly search through the hash bucket
3291         for( ; item ; item = item->next ) {
3292                 if( !strcmp( item->basename, basename ) ) {
3293                         return item;
3294                 }
3295         }
3296         return NULL;
3297 }
3298
3299 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3300 {
3301         skinframe_t *item;
3302         int hashindex;
3303         char basename[MAX_QPATH];
3304
3305         Image_StripImageExtension(name, basename, sizeof(basename));
3306
3307         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3308         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3309                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3310                         break;
3311
3312         if (!item) {
3313                 rtexture_t *dyntexture;
3314                 // check whether its a dynamic texture
3315                 dyntexture = CL_GetDynTexture( basename );
3316                 if (!add && !dyntexture)
3317                         return NULL;
3318                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3319                 memset(item, 0, sizeof(*item));
3320                 strlcpy(item->basename, basename, sizeof(item->basename));
3321                 item->base = dyntexture; // either NULL or dyntexture handle
3322                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3323                 item->comparewidth = comparewidth;
3324                 item->compareheight = compareheight;
3325                 item->comparecrc = comparecrc;
3326                 item->next = r_skinframe.hash[hashindex];
3327                 r_skinframe.hash[hashindex] = item;
3328         }
3329         else if (textureflags & TEXF_FORCE_RELOAD)
3330         {
3331                 rtexture_t *dyntexture;
3332                 // check whether its a dynamic texture
3333                 dyntexture = CL_GetDynTexture( basename );
3334                 if (!add && !dyntexture)
3335                         return NULL;
3336                 if (item->merged == item->base)
3337                         item->merged = NULL;
3338                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3339                 R_PurgeTexture(item->stain );item->stain  = NULL;
3340                 R_PurgeTexture(item->merged);item->merged = NULL;
3341                 R_PurgeTexture(item->base  );item->base   = NULL;
3342                 R_PurgeTexture(item->pants );item->pants  = NULL;
3343                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3344                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3345                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3346                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3347                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3348         R_PurgeTexture(item->reflect);item->reflect = NULL;
3349                 item->loadsequence = 0;
3350         }
3351         else if( item->base == NULL )
3352         {
3353                 rtexture_t *dyntexture;
3354                 // check whether its a dynamic texture
3355                 // 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]
3356                 dyntexture = CL_GetDynTexture( basename );
3357                 item->base = dyntexture; // either NULL or dyntexture handle
3358         }
3359
3360         R_SkinFrame_MarkUsed(item);
3361         return item;
3362 }
3363
3364 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3365         { \
3366                 unsigned long long avgcolor[5], wsum; \
3367                 int pix, comp, w; \
3368                 avgcolor[0] = 0; \
3369                 avgcolor[1] = 0; \
3370                 avgcolor[2] = 0; \
3371                 avgcolor[3] = 0; \
3372                 avgcolor[4] = 0; \
3373                 wsum = 0; \
3374                 for(pix = 0; pix < cnt; ++pix) \
3375                 { \
3376                         w = 0; \
3377                         for(comp = 0; comp < 3; ++comp) \
3378                                 w += getpixel; \
3379                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3380                         { \
3381                                 ++wsum; \
3382                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3383                                 w = getpixel; \
3384                                 for(comp = 0; comp < 3; ++comp) \
3385                                         avgcolor[comp] += getpixel * w; \
3386                                 avgcolor[3] += w; \
3387                         } \
3388                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3389                         avgcolor[4] += getpixel; \
3390                 } \
3391                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3392                         avgcolor[3] = 1; \
3393                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3394                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3395                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3396                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3397         }
3398
3399 extern cvar_t gl_picmip;
3400 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3401 {
3402         int j;
3403         unsigned char *pixels;
3404         unsigned char *bumppixels;
3405         unsigned char *basepixels = NULL;
3406         int basepixels_width = 0;
3407         int basepixels_height = 0;
3408         skinframe_t *skinframe;
3409         rtexture_t *ddsbase = NULL;
3410         qboolean ddshasalpha = false;
3411         float ddsavgcolor[4];
3412         char basename[MAX_QPATH];
3413         int miplevel = R_PicmipForFlags(textureflags);
3414         int savemiplevel = miplevel;
3415         int mymiplevel;
3416         char vabuf[1024];
3417
3418         if (cls.state == ca_dedicated)
3419                 return NULL;
3420
3421         // return an existing skinframe if already loaded
3422         // if loading of the first image fails, don't make a new skinframe as it
3423         // would cause all future lookups of this to be missing
3424         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3425         if (skinframe && skinframe->base)
3426                 return skinframe;
3427
3428         Image_StripImageExtension(name, basename, sizeof(basename));
3429
3430         // check for DDS texture file first
3431         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3432         {
3433                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3434                 if (basepixels == NULL)
3435                         return NULL;
3436         }
3437
3438         // FIXME handle miplevel
3439
3440         if (developer_loading.integer)
3441                 Con_Printf("loading skin \"%s\"\n", name);
3442
3443         // we've got some pixels to store, so really allocate this new texture now
3444         if (!skinframe)
3445                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3446         textureflags &= ~TEXF_FORCE_RELOAD;
3447         skinframe->stain = NULL;
3448         skinframe->merged = NULL;
3449         skinframe->base = NULL;
3450         skinframe->pants = NULL;
3451         skinframe->shirt = NULL;
3452         skinframe->nmap = NULL;
3453         skinframe->gloss = NULL;
3454         skinframe->glow = NULL;
3455         skinframe->fog = NULL;
3456         skinframe->reflect = NULL;
3457         skinframe->hasalpha = false;
3458         // we could store the q2animname here too
3459
3460         if (ddsbase)
3461         {
3462                 skinframe->base = ddsbase;
3463                 skinframe->hasalpha = ddshasalpha;
3464                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3465                 if (r_loadfog && skinframe->hasalpha)
3466                         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);
3467                 //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]);
3468         }
3469         else
3470         {
3471                 basepixels_width = image_width;
3472                 basepixels_height = image_height;
3473                 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);
3474                 if (textureflags & TEXF_ALPHA)
3475                 {
3476                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3477                         {
3478                                 if (basepixels[j] < 255)
3479                                 {
3480                                         skinframe->hasalpha = true;
3481                                         break;
3482                                 }
3483                         }
3484                         if (r_loadfog && skinframe->hasalpha)
3485                         {
3486                                 // has transparent pixels
3487                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3488                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3489                                 {
3490                                         pixels[j+0] = 255;
3491                                         pixels[j+1] = 255;
3492                                         pixels[j+2] = 255;
3493                                         pixels[j+3] = basepixels[j+3];
3494                                 }
3495                                 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);
3496                                 Mem_Free(pixels);
3497                         }
3498                 }
3499                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3500 #ifndef USE_GLES2
3501                 //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]);
3502                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3503                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3504                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3505                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3506 #endif
3507         }
3508
3509         if (r_loaddds)
3510         {
3511                 mymiplevel = savemiplevel;
3512                 if (r_loadnormalmap)
3513                         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);
3514                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3515                 if (r_loadgloss)
3516                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3517                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3518                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3519                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3520         }
3521
3522         // _norm is the name used by tenebrae and has been adopted as standard
3523         if (r_loadnormalmap && skinframe->nmap == NULL)
3524         {
3525                 mymiplevel = savemiplevel;
3526                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3527                 {
3528                         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);
3529                         Mem_Free(pixels);
3530                         pixels = NULL;
3531                 }
3532                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3533                 {
3534                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3535                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3536                         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);
3537                         Mem_Free(pixels);
3538                         Mem_Free(bumppixels);
3539                 }
3540                 else if (r_shadow_bumpscale_basetexture.value > 0)
3541                 {
3542                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3543                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3544                         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);
3545                         Mem_Free(pixels);
3546                 }
3547 #ifndef USE_GLES2
3548                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3549                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3550 #endif
3551         }
3552
3553         // _luma is supported only for tenebrae compatibility
3554         // _glow is the preferred name
3555         mymiplevel = savemiplevel;
3556         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))))
3557         {
3558                 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);
3559 #ifndef USE_GLES2
3560                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3561                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3562 #endif
3563                 Mem_Free(pixels);pixels = NULL;
3564         }
3565
3566         mymiplevel = savemiplevel;
3567         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3568         {
3569                 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);
3570 #ifndef USE_GLES2
3571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3572                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3573 #endif
3574                 Mem_Free(pixels);
3575                 pixels = NULL;
3576         }
3577
3578         mymiplevel = savemiplevel;
3579         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3580         {
3581                 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);
3582 #ifndef USE_GLES2
3583                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3584                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.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->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3592         {
3593                 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);
3594 #ifndef USE_GLES2
3595                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3596                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3597 #endif
3598                 Mem_Free(pixels);
3599                 pixels = NULL;
3600         }
3601
3602         mymiplevel = savemiplevel;
3603         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3604         {
3605                 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);
3606 #ifndef USE_GLES2
3607                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3608                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3609 #endif
3610                 Mem_Free(pixels);
3611                 pixels = NULL;
3612         }
3613
3614         if (basepixels)
3615                 Mem_Free(basepixels);
3616
3617         return skinframe;
3618 }
3619
3620 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3621 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3622 {
3623         int i;
3624         skinframe_t *skinframe;
3625         char vabuf[1024];
3626
3627         if (cls.state == ca_dedicated)
3628                 return NULL;
3629
3630         // if already loaded just return it, otherwise make a new skinframe
3631         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3632         if (skinframe->base)
3633                 return skinframe;
3634         textureflags &= ~TEXF_FORCE_RELOAD;
3635
3636         skinframe->stain = NULL;
3637         skinframe->merged = NULL;
3638         skinframe->base = NULL;
3639         skinframe->pants = NULL;
3640         skinframe->shirt = NULL;
3641         skinframe->nmap = NULL;
3642         skinframe->gloss = NULL;
3643         skinframe->glow = NULL;
3644         skinframe->fog = NULL;
3645         skinframe->reflect = NULL;
3646         skinframe->hasalpha = false;
3647
3648         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3649         if (!skindata)
3650                 return NULL;
3651
3652         if (developer_loading.integer)
3653                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3654
3655         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3656         {
3657                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3658                 unsigned char *b = a + width * height * 4;
3659                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3660                 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);
3661                 Mem_Free(a);
3662         }
3663         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3664         if (textureflags & TEXF_ALPHA)
3665         {
3666                 for (i = 3;i < width * height * 4;i += 4)
3667                 {
3668                         if (skindata[i] < 255)
3669                         {
3670                                 skinframe->hasalpha = true;
3671                                 break;
3672                         }
3673                 }
3674                 if (r_loadfog && skinframe->hasalpha)
3675                 {
3676                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3677                         memcpy(fogpixels, skindata, width * height * 4);
3678                         for (i = 0;i < width * height * 4;i += 4)
3679                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3680                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3681                         Mem_Free(fogpixels);
3682                 }
3683         }
3684
3685         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3686         //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]);
3687
3688         return skinframe;
3689 }
3690
3691 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3692 {
3693         int i;
3694         int featuresmask;
3695         skinframe_t *skinframe;
3696
3697         if (cls.state == ca_dedicated)
3698                 return NULL;
3699
3700         // if already loaded just return it, otherwise make a new skinframe
3701         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3702         if (skinframe->base)
3703                 return skinframe;
3704         //textureflags &= ~TEXF_FORCE_RELOAD;
3705
3706         skinframe->stain = NULL;
3707         skinframe->merged = NULL;
3708         skinframe->base = NULL;
3709         skinframe->pants = NULL;
3710         skinframe->shirt = NULL;
3711         skinframe->nmap = NULL;
3712         skinframe->gloss = NULL;
3713         skinframe->glow = NULL;
3714         skinframe->fog = NULL;
3715         skinframe->reflect = NULL;
3716         skinframe->hasalpha = false;
3717
3718         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3719         if (!skindata)
3720                 return NULL;
3721
3722         if (developer_loading.integer)
3723                 Con_Printf("loading quake skin \"%s\"\n", name);
3724
3725         // 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)
3726         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3727         memcpy(skinframe->qpixels, skindata, width*height);
3728         skinframe->qwidth = width;
3729         skinframe->qheight = height;
3730
3731         featuresmask = 0;
3732         for (i = 0;i < width * height;i++)
3733                 featuresmask |= palette_featureflags[skindata[i]];
3734
3735         skinframe->hasalpha = false;
3736         // fence textures
3737         if (name[0] == '{')
3738                 skinframe->hasalpha = true;
3739         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3740         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3741         skinframe->qgeneratemerged = true;
3742         skinframe->qgeneratebase = skinframe->qhascolormapping;
3743         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3744
3745         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3746         //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]);
3747
3748         return skinframe;
3749 }
3750
3751 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3752 {
3753         int width;
3754         int height;
3755         unsigned char *skindata;
3756         char vabuf[1024];
3757
3758         if (!skinframe->qpixels)
3759                 return;
3760
3761         if (!skinframe->qhascolormapping)
3762                 colormapped = false;
3763
3764         if (colormapped)
3765         {
3766                 if (!skinframe->qgeneratebase)
3767                         return;
3768         }
3769         else
3770         {
3771                 if (!skinframe->qgeneratemerged)
3772                         return;
3773         }
3774
3775         width = skinframe->qwidth;
3776         height = skinframe->qheight;
3777         skindata = skinframe->qpixels;
3778
3779         if (skinframe->qgeneratenmap)
3780         {
3781                 unsigned char *a, *b;
3782                 skinframe->qgeneratenmap = false;
3783                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3784                 b = a + width * height * 4;
3785                 // use either a custom palette or the quake palette
3786                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3787                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3788                 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);
3789                 Mem_Free(a);
3790         }
3791
3792         if (skinframe->qgenerateglow)
3793         {
3794                 skinframe->qgenerateglow = false;
3795                 if (skinframe->hasalpha) // fence textures
3796                         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
3797                 else
3798                         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
3799         }
3800
3801         if (colormapped)
3802         {
3803                 skinframe->qgeneratebase = false;
3804                 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);
3805                 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);
3806                 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);
3807         }
3808         else
3809         {
3810                 skinframe->qgeneratemerged = false;
3811                 if (skinframe->hasalpha) // fence textures
3812                         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);
3813                 else
3814                         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);
3815         }
3816
3817         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3818         {
3819                 Mem_Free(skinframe->qpixels);
3820                 skinframe->qpixels = NULL;
3821         }
3822 }
3823
3824 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)
3825 {
3826         int i;
3827         skinframe_t *skinframe;
3828         char vabuf[1024];
3829
3830         if (cls.state == ca_dedicated)
3831                 return NULL;
3832
3833         // if already loaded just return it, otherwise make a new skinframe
3834         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3835         if (skinframe->base)
3836                 return skinframe;
3837         textureflags &= ~TEXF_FORCE_RELOAD;
3838
3839         skinframe->stain = NULL;
3840         skinframe->merged = NULL;
3841         skinframe->base = NULL;
3842         skinframe->pants = NULL;
3843         skinframe->shirt = NULL;
3844         skinframe->nmap = NULL;
3845         skinframe->gloss = NULL;
3846         skinframe->glow = NULL;
3847         skinframe->fog = NULL;
3848         skinframe->reflect = NULL;
3849         skinframe->hasalpha = false;
3850
3851         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3852         if (!skindata)
3853                 return NULL;
3854
3855         if (developer_loading.integer)
3856                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3857
3858         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3859         if (textureflags & TEXF_ALPHA)
3860         {
3861                 for (i = 0;i < width * height;i++)
3862                 {
3863                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3864                         {
3865                                 skinframe->hasalpha = true;
3866                                 break;
3867                         }
3868                 }
3869                 if (r_loadfog && skinframe->hasalpha)
3870                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3871         }
3872
3873         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3874         //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]);
3875
3876         return skinframe;
3877 }
3878
3879 skinframe_t *R_SkinFrame_LoadMissing(void)
3880 {
3881         skinframe_t *skinframe;
3882
3883         if (cls.state == ca_dedicated)
3884                 return NULL;
3885
3886         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3887         skinframe->stain = NULL;
3888         skinframe->merged = NULL;
3889         skinframe->base = NULL;
3890         skinframe->pants = NULL;
3891         skinframe->shirt = NULL;
3892         skinframe->nmap = NULL;
3893         skinframe->gloss = NULL;
3894         skinframe->glow = NULL;
3895         skinframe->fog = NULL;
3896         skinframe->reflect = NULL;
3897         skinframe->hasalpha = false;
3898
3899         skinframe->avgcolor[0] = rand() / RAND_MAX;
3900         skinframe->avgcolor[1] = rand() / RAND_MAX;
3901         skinframe->avgcolor[2] = rand() / RAND_MAX;
3902         skinframe->avgcolor[3] = 1;
3903
3904         return skinframe;
3905 }
3906
3907 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3908 typedef struct suffixinfo_s
3909 {
3910         const char *suffix;
3911         qboolean flipx, flipy, flipdiagonal;
3912 }
3913 suffixinfo_t;
3914 static suffixinfo_t suffix[3][6] =
3915 {
3916         {
3917                 {"px",   false, false, false},
3918                 {"nx",   false, false, false},
3919                 {"py",   false, false, false},
3920                 {"ny",   false, false, false},
3921                 {"pz",   false, false, false},
3922                 {"nz",   false, false, false}
3923         },
3924         {
3925                 {"posx", false, false, false},
3926                 {"negx", false, false, false},
3927                 {"posy", false, false, false},
3928                 {"negy", false, false, false},
3929                 {"posz", false, false, false},
3930                 {"negz", false, false, false}
3931         },
3932         {
3933                 {"rt",    true, false,  true},
3934                 {"lf",   false,  true,  true},
3935                 {"ft",    true,  true, false},
3936                 {"bk",   false, false, false},
3937                 {"up",    true, false,  true},
3938                 {"dn",    true, false,  true}
3939         }
3940 };
3941
3942 static int componentorder[4] = {0, 1, 2, 3};
3943
3944 static rtexture_t *R_LoadCubemap(const char *basename)
3945 {
3946         int i, j, cubemapsize;
3947         unsigned char *cubemappixels, *image_buffer;
3948         rtexture_t *cubemaptexture;
3949         char name[256];
3950         // must start 0 so the first loadimagepixels has no requested width/height
3951         cubemapsize = 0;
3952         cubemappixels = NULL;
3953         cubemaptexture = NULL;
3954         // keep trying different suffix groups (posx, px, rt) until one loads
3955         for (j = 0;j < 3 && !cubemappixels;j++)
3956         {
3957                 // load the 6 images in the suffix group
3958                 for (i = 0;i < 6;i++)
3959                 {
3960                         // generate an image name based on the base and and suffix
3961                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3962                         // load it
3963                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3964                         {
3965                                 // an image loaded, make sure width and height are equal
3966                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3967                                 {
3968                                         // if this is the first image to load successfully, allocate the cubemap memory
3969                                         if (!cubemappixels && image_width >= 1)
3970                                         {
3971                                                 cubemapsize = image_width;
3972                                                 // note this clears to black, so unavailable sides are black
3973                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3974                                         }
3975                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3976                                         if (cubemappixels)
3977                                                 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);
3978                                 }
3979                                 else
3980                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3981                                 // free the image
3982                                 Mem_Free(image_buffer);
3983                         }
3984                 }
3985         }
3986         // if a cubemap loaded, upload it
3987         if (cubemappixels)
3988         {
3989                 if (developer_loading.integer)
3990                         Con_Printf("loading cubemap \"%s\"\n", basename);
3991
3992                 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);
3993                 Mem_Free(cubemappixels);
3994         }
3995         else
3996         {
3997                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3998                 if (developer_loading.integer)
3999                 {
4000                         Con_Printf("(tried tried images ");
4001                         for (j = 0;j < 3;j++)
4002                                 for (i = 0;i < 6;i++)
4003                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
4004                         Con_Print(" and was unable to find any of them).\n");
4005                 }
4006         }
4007         return cubemaptexture;
4008 }
4009
4010 rtexture_t *R_GetCubemap(const char *basename)
4011 {
4012         int i;
4013         for (i = 0;i < r_texture_numcubemaps;i++)
4014                 if (r_texture_cubemaps[i] != NULL)
4015                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4016                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4017         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4018                 return r_texture_whitecube;
4019         r_texture_numcubemaps++;
4020         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4021         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4022         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4023         return r_texture_cubemaps[i]->texture;
4024 }
4025
4026 static void R_Main_FreeViewCache(void)
4027 {
4028         if (r_refdef.viewcache.entityvisible)
4029                 Mem_Free(r_refdef.viewcache.entityvisible);
4030         if (r_refdef.viewcache.world_pvsbits)
4031                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4032         if (r_refdef.viewcache.world_leafvisible)
4033                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4034         if (r_refdef.viewcache.world_surfacevisible)
4035                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4036         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4037 }
4038
4039 static void R_Main_ResizeViewCache(void)
4040 {
4041         int numentities = r_refdef.scene.numentities;
4042         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4043         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4044         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4045         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4046         if (r_refdef.viewcache.maxentities < numentities)
4047         {
4048                 r_refdef.viewcache.maxentities = numentities;
4049                 if (r_refdef.viewcache.entityvisible)
4050                         Mem_Free(r_refdef.viewcache.entityvisible);
4051                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4052         }
4053         if (r_refdef.viewcache.world_numclusters != numclusters)
4054         {
4055                 r_refdef.viewcache.world_numclusters = numclusters;
4056                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4057                 if (r_refdef.viewcache.world_pvsbits)
4058                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4059                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4060         }
4061         if (r_refdef.viewcache.world_numleafs != numleafs)
4062         {
4063                 r_refdef.viewcache.world_numleafs = numleafs;
4064                 if (r_refdef.viewcache.world_leafvisible)
4065                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4066                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4067         }
4068         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4069         {
4070                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4071                 if (r_refdef.viewcache.world_surfacevisible)
4072                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4073                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4074         }
4075 }
4076
4077 extern rtexture_t *loadingscreentexture;
4078 static void gl_main_start(void)
4079 {
4080         loadingscreentexture = NULL;
4081         r_texture_blanknormalmap = NULL;
4082         r_texture_white = NULL;
4083         r_texture_grey128 = NULL;
4084         r_texture_black = NULL;
4085         r_texture_whitecube = NULL;
4086         r_texture_normalizationcube = NULL;
4087         r_texture_fogattenuation = NULL;
4088         r_texture_fogheighttexture = NULL;
4089         r_texture_gammaramps = NULL;
4090         r_texture_numcubemaps = 0;
4091         r_uniformbufferalignment = 32;
4092
4093         r_loaddds = r_texture_dds_load.integer != 0;
4094         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4095
4096         switch(vid.renderpath)
4097         {
4098         case RENDERPATH_GL20:
4099         case RENDERPATH_D3D9:
4100         case RENDERPATH_D3D10:
4101         case RENDERPATH_D3D11:
4102         case RENDERPATH_SOFT:
4103         case RENDERPATH_GLES2:
4104                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4105                 Cvar_SetValueQuick(&gl_combine, 1);
4106                 Cvar_SetValueQuick(&r_glsl, 1);
4107                 r_loadnormalmap = true;
4108                 r_loadgloss = true;
4109                 r_loadfog = false;
4110 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4111                 if (vid.support.arb_uniform_buffer_object)
4112                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4113 #endif
4114                         break;
4115         case RENDERPATH_GL13:
4116         case RENDERPATH_GLES1:
4117                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4118                 Cvar_SetValueQuick(&gl_combine, 1);
4119                 Cvar_SetValueQuick(&r_glsl, 0);
4120                 r_loadnormalmap = false;
4121                 r_loadgloss = false;
4122                 r_loadfog = true;
4123                 break;
4124         case RENDERPATH_GL11:
4125                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4126                 Cvar_SetValueQuick(&gl_combine, 0);
4127                 Cvar_SetValueQuick(&r_glsl, 0);
4128                 r_loadnormalmap = false;
4129                 r_loadgloss = false;
4130                 r_loadfog = true;
4131                 break;
4132         }
4133
4134         R_AnimCache_Free();
4135         R_FrameData_Reset();
4136         R_BufferData_Reset();
4137
4138         r_numqueries = 0;
4139         r_maxqueries = 0;
4140         memset(r_queries, 0, sizeof(r_queries));
4141
4142         r_qwskincache = NULL;
4143         r_qwskincache_size = 0;
4144
4145         // due to caching of texture_t references, the collision cache must be reset
4146         Collision_Cache_Reset(true);
4147
4148         // set up r_skinframe loading system for textures
4149         memset(&r_skinframe, 0, sizeof(r_skinframe));
4150         r_skinframe.loadsequence = 1;
4151         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4152
4153         r_main_texturepool = R_AllocTexturePool();
4154         R_BuildBlankTextures();
4155         R_BuildNoTexture();
4156         if (vid.support.arb_texture_cube_map)
4157         {
4158                 R_BuildWhiteCube();
4159                 R_BuildNormalizationCube();
4160         }
4161         r_texture_fogattenuation = NULL;
4162         r_texture_fogheighttexture = NULL;
4163         r_texture_gammaramps = NULL;
4164         //r_texture_fogintensity = NULL;
4165         memset(&r_fb, 0, sizeof(r_fb));
4166         r_glsl_permutation = NULL;
4167         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4168         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4169 #ifdef SUPPORTD3D
4170         r_hlsl_permutation = NULL;
4171         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4172         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4173 #endif
4174         memset(&r_svbsp, 0, sizeof (r_svbsp));
4175
4176         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4177         r_texture_numcubemaps = 0;
4178
4179         r_refdef.fogmasktable_density = 0;
4180
4181 #ifdef __ANDROID__
4182         // For Steelstorm Android
4183         // FIXME CACHE the program and reload
4184         // FIXME see possible combinations for SS:BR android
4185         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4186         R_SetupShader_SetPermutationGLSL(0, 12);
4187         R_SetupShader_SetPermutationGLSL(0, 13);
4188         R_SetupShader_SetPermutationGLSL(0, 8388621);
4189         R_SetupShader_SetPermutationGLSL(3, 0);
4190         R_SetupShader_SetPermutationGLSL(3, 2048);
4191         R_SetupShader_SetPermutationGLSL(5, 0);
4192         R_SetupShader_SetPermutationGLSL(5, 2);
4193         R_SetupShader_SetPermutationGLSL(5, 2048);
4194         R_SetupShader_SetPermutationGLSL(5, 8388608);
4195         R_SetupShader_SetPermutationGLSL(11, 1);
4196         R_SetupShader_SetPermutationGLSL(11, 2049);
4197         R_SetupShader_SetPermutationGLSL(11, 8193);
4198         R_SetupShader_SetPermutationGLSL(11, 10241);
4199         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4200 #endif
4201 }
4202
4203 static void gl_main_shutdown(void)
4204 {
4205         R_AnimCache_Free();
4206         R_FrameData_Reset();
4207         R_BufferData_Reset();
4208
4209         R_Main_FreeViewCache();
4210
4211         switch(vid.renderpath)
4212         {
4213         case RENDERPATH_GL11:
4214         case RENDERPATH_GL13:
4215         case RENDERPATH_GL20:
4216         case RENDERPATH_GLES1:
4217         case RENDERPATH_GLES2:
4218 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4219                 if (r_maxqueries)
4220                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4221 #endif
4222                 break;
4223         case RENDERPATH_D3D9:
4224                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4225                 break;
4226         case RENDERPATH_D3D10:
4227                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4228                 break;
4229         case RENDERPATH_D3D11:
4230                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4231                 break;
4232         case RENDERPATH_SOFT:
4233                 break;
4234         }
4235
4236         r_numqueries = 0;
4237         r_maxqueries = 0;
4238         memset(r_queries, 0, sizeof(r_queries));
4239
4240         r_qwskincache = NULL;
4241         r_qwskincache_size = 0;
4242
4243         // clear out the r_skinframe state
4244         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4245         memset(&r_skinframe, 0, sizeof(r_skinframe));
4246
4247         if (r_svbsp.nodes)
4248                 Mem_Free(r_svbsp.nodes);
4249         memset(&r_svbsp, 0, sizeof (r_svbsp));
4250         R_FreeTexturePool(&r_main_texturepool);
4251         loadingscreentexture = NULL;
4252         r_texture_blanknormalmap = NULL;
4253         r_texture_white = NULL;
4254         r_texture_grey128 = NULL;
4255         r_texture_black = NULL;
4256         r_texture_whitecube = NULL;
4257         r_texture_normalizationcube = NULL;
4258         r_texture_fogattenuation = NULL;
4259         r_texture_fogheighttexture = NULL;
4260         r_texture_gammaramps = NULL;
4261         r_texture_numcubemaps = 0;
4262         //r_texture_fogintensity = NULL;
4263         memset(&r_fb, 0, sizeof(r_fb));
4264         R_GLSL_Restart_f();
4265
4266         r_glsl_permutation = NULL;
4267         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4268         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4269 #ifdef SUPPORTD3D
4270         r_hlsl_permutation = NULL;
4271         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4272         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4273 #endif
4274 }
4275
4276 static void gl_main_newmap(void)
4277 {
4278         // FIXME: move this code to client
4279         char *entities, entname[MAX_QPATH];
4280         if (r_qwskincache)
4281                 Mem_Free(r_qwskincache);
4282         r_qwskincache = NULL;
4283         r_qwskincache_size = 0;
4284         if (cl.worldmodel)
4285         {
4286                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4287                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4288                 {
4289                         CL_ParseEntityLump(entities);
4290                         Mem_Free(entities);
4291                         return;
4292                 }
4293                 if (cl.worldmodel->brush.entities)
4294                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4295         }
4296         R_Main_FreeViewCache();
4297
4298         R_FrameData_Reset();
4299         R_BufferData_Reset();
4300 }
4301
4302 void GL_Main_Init(void)
4303 {
4304         int i;
4305         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4306         R_InitShaderModeInfo();
4307
4308         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4309         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4310         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4311         if (gamemode == GAME_NEHAHRA)
4312         {
4313                 Cvar_RegisterVariable (&gl_fogenable);
4314                 Cvar_RegisterVariable (&gl_fogdensity);
4315                 Cvar_RegisterVariable (&gl_fogred);
4316                 Cvar_RegisterVariable (&gl_foggreen);
4317                 Cvar_RegisterVariable (&gl_fogblue);
4318                 Cvar_RegisterVariable (&gl_fogstart);
4319                 Cvar_RegisterVariable (&gl_fogend);
4320                 Cvar_RegisterVariable (&gl_skyclip);
4321         }
4322         Cvar_RegisterVariable(&r_motionblur);
4323         Cvar_RegisterVariable(&r_damageblur);
4324         Cvar_RegisterVariable(&r_motionblur_averaging);
4325         Cvar_RegisterVariable(&r_motionblur_randomize);
4326         Cvar_RegisterVariable(&r_motionblur_minblur);
4327         Cvar_RegisterVariable(&r_motionblur_maxblur);
4328         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4329         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4330         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4331         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4332         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4333         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4334         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4335         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4336         Cvar_RegisterVariable(&r_equalize_entities_by);
4337         Cvar_RegisterVariable(&r_equalize_entities_to);
4338         Cvar_RegisterVariable(&r_depthfirst);
4339         Cvar_RegisterVariable(&r_useinfinitefarclip);
4340         Cvar_RegisterVariable(&r_farclip_base);
4341         Cvar_RegisterVariable(&r_farclip_world);
4342         Cvar_RegisterVariable(&r_nearclip);
4343         Cvar_RegisterVariable(&r_deformvertexes);
4344         Cvar_RegisterVariable(&r_transparent);
4345         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4346         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4347         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4348         Cvar_RegisterVariable(&r_showoverdraw);
4349         Cvar_RegisterVariable(&r_showbboxes);
4350         Cvar_RegisterVariable(&r_showbboxes_client);
4351         Cvar_RegisterVariable(&r_showsurfaces);
4352         Cvar_RegisterVariable(&r_showtris);
4353         Cvar_RegisterVariable(&r_shownormals);
4354         Cvar_RegisterVariable(&r_showlighting);
4355         Cvar_RegisterVariable(&r_showshadowvolumes);
4356         Cvar_RegisterVariable(&r_showcollisionbrushes);
4357         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4358         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4359         Cvar_RegisterVariable(&r_showdisabledepthtest);
4360         Cvar_RegisterVariable(&r_drawportals);
4361         Cvar_RegisterVariable(&r_drawentities);
4362         Cvar_RegisterVariable(&r_draw2d);
4363         Cvar_RegisterVariable(&r_drawworld);
4364         Cvar_RegisterVariable(&r_cullentities_trace);
4365         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4366         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4367         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4368         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4369         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4370         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4371         Cvar_RegisterVariable(&r_sortentities);
4372         Cvar_RegisterVariable(&r_drawviewmodel);
4373         Cvar_RegisterVariable(&r_drawexteriormodel);
4374         Cvar_RegisterVariable(&r_speeds);
4375         Cvar_RegisterVariable(&r_fullbrights);
4376         Cvar_RegisterVariable(&r_wateralpha);
4377         Cvar_RegisterVariable(&r_dynamic);
4378         Cvar_RegisterVariable(&r_fakelight);
4379         Cvar_RegisterVariable(&r_fakelight_intensity);
4380         Cvar_RegisterVariable(&r_fullbright_directed);
4381         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4382         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4383         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4384         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4385         Cvar_RegisterVariable(&r_fullbright);
4386         Cvar_RegisterVariable(&r_shadows);
4387         Cvar_RegisterVariable(&r_shadows_darken);
4388         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4389         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4390         Cvar_RegisterVariable(&r_shadows_throwdistance);
4391         Cvar_RegisterVariable(&r_shadows_throwdirection);
4392         Cvar_RegisterVariable(&r_shadows_focus);
4393         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4394         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4395         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4396         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4397         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4398         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4399         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4400         Cvar_RegisterVariable(&r_fog_exp2);
4401         Cvar_RegisterVariable(&r_fog_clear);
4402         Cvar_RegisterVariable(&r_drawfog);
4403         Cvar_RegisterVariable(&r_transparentdepthmasking);
4404         Cvar_RegisterVariable(&r_transparent_sortmindist);
4405         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4406         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4407         Cvar_RegisterVariable(&r_texture_dds_load);
4408         Cvar_RegisterVariable(&r_texture_dds_save);
4409         Cvar_RegisterVariable(&r_textureunits);
4410         Cvar_RegisterVariable(&gl_combine);
4411         Cvar_RegisterVariable(&r_usedepthtextures);
4412         Cvar_RegisterVariable(&r_viewfbo);
4413         Cvar_RegisterVariable(&r_viewscale);
4414         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4415         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4416         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4417         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4418         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4419         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4420         Cvar_RegisterVariable(&r_glsl);
4421         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4422         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4423         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4424         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4425         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4426         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4427         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4428         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4429         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4430         Cvar_RegisterVariable(&r_glsl_postprocess);
4431         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4432         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4433         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4434         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4435         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4436         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4437         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4438         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4439         Cvar_RegisterVariable(&r_celshading);
4440         Cvar_RegisterVariable(&r_celoutlines);
4441
4442         Cvar_RegisterVariable(&r_water);
4443         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4444         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4445         Cvar_RegisterVariable(&r_water_clippingplanebias);
4446         Cvar_RegisterVariable(&r_water_refractdistort);
4447         Cvar_RegisterVariable(&r_water_reflectdistort);
4448         Cvar_RegisterVariable(&r_water_scissormode);
4449         Cvar_RegisterVariable(&r_water_lowquality);
4450         Cvar_RegisterVariable(&r_water_hideplayer);
4451         Cvar_RegisterVariable(&r_water_fbo);
4452
4453         Cvar_RegisterVariable(&r_lerpsprites);
4454         Cvar_RegisterVariable(&r_lerpmodels);
4455         Cvar_RegisterVariable(&r_lerplightstyles);
4456         Cvar_RegisterVariable(&r_waterscroll);
4457         Cvar_RegisterVariable(&r_bloom);
4458         Cvar_RegisterVariable(&r_bloom_colorscale);
4459         Cvar_RegisterVariable(&r_bloom_brighten);
4460         Cvar_RegisterVariable(&r_bloom_blur);
4461         Cvar_RegisterVariable(&r_bloom_resolution);
4462         Cvar_RegisterVariable(&r_bloom_colorexponent);
4463         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4464         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4465         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4466         Cvar_RegisterVariable(&r_hdr_glowintensity);
4467         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4468         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4469         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4470         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4471         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4472         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4473         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4474         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4475         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4476         Cvar_RegisterVariable(&developer_texturelogging);
4477         Cvar_RegisterVariable(&gl_lightmaps);
4478         Cvar_RegisterVariable(&r_test);
4479         Cvar_RegisterVariable(&r_batch_multidraw);
4480         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4481         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4482         Cvar_RegisterVariable(&r_glsl_skeletal);
4483         Cvar_RegisterVariable(&r_glsl_saturation);
4484         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4485         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4486         Cvar_RegisterVariable(&r_framedatasize);
4487         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4488                 Cvar_RegisterVariable(&r_buffermegs[i]);
4489         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4490         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4491                 Cvar_SetValue("r_fullbrights", 0);
4492 #ifdef DP_MOBILETOUCH
4493         // GLES devices have terrible depth precision in general, so...
4494         Cvar_SetValueQuick(&r_nearclip, 4);
4495         Cvar_SetValueQuick(&r_farclip_base, 4096);
4496         Cvar_SetValueQuick(&r_farclip_world, 0);
4497         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4498 #endif
4499         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4500 }
4501
4502 void Render_Init(void)
4503 {
4504         gl_backend_init();
4505         R_Textures_Init();
4506         GL_Main_Init();
4507         Font_Init();
4508         GL_Draw_Init();
4509         R_Shadow_Init();
4510         R_Sky_Init();
4511         GL_Surf_Init();
4512         Sbar_Init();
4513         R_Particles_Init();
4514         R_Explosion_Init();
4515         R_LightningBeams_Init();
4516         Mod_RenderInit();
4517 }
4518
4519 /*
4520 ===============
4521 GL_Init
4522 ===============
4523 */
4524 #ifndef USE_GLES2
4525 extern char *ENGINE_EXTENSIONS;
4526 void GL_Init (void)
4527 {
4528         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4529         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4530         gl_version = (const char *)qglGetString(GL_VERSION);
4531         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4532
4533         if (!gl_extensions)
4534                 gl_extensions = "";
4535         if (!gl_platformextensions)
4536                 gl_platformextensions = "";
4537
4538         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4539         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4540         Con_Printf("GL_VERSION: %s\n", gl_version);
4541         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4542         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4543
4544         VID_CheckExtensions();
4545
4546         // LordHavoc: report supported extensions
4547 #ifdef CONFIG_MENU
4548         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4549 #else
4550         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4551 #endif
4552
4553         // clear to black (loading plaque will be seen over this)
4554         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4555 }
4556 #endif
4557
4558 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4559 {
4560         int i;
4561         mplane_t *p;
4562         if (r_trippy.integer)
4563                 return false;
4564         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4565         {
4566                 p = r_refdef.view.frustum + i;
4567                 switch(p->signbits)
4568                 {
4569                 default:
4570                 case 0:
4571                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 1:
4575                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 2:
4579                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 case 3:
4583                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4584                                 return true;
4585                         break;
4586                 case 4:
4587                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4588                                 return true;
4589                         break;
4590                 case 5:
4591                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4592                                 return true;
4593                         break;
4594                 case 6:
4595                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4596                                 return true;
4597                         break;
4598                 case 7:
4599                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4600                                 return true;
4601                         break;
4602                 }
4603         }
4604         return false;
4605 }
4606
4607 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4608 {
4609         int i;
4610         const mplane_t *p;
4611         if (r_trippy.integer)
4612                 return false;
4613         for (i = 0;i < numplanes;i++)
4614         {
4615                 p = planes + i;
4616                 switch(p->signbits)
4617                 {
4618                 default:
4619                 case 0:
4620                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4621                                 return true;
4622                         break;
4623                 case 1:
4624                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4625                                 return true;
4626                         break;
4627                 case 2:
4628                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4629                                 return true;
4630                         break;
4631                 case 3:
4632                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4633                                 return true;
4634                         break;
4635                 case 4:
4636                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4637                                 return true;
4638                         break;
4639                 case 5:
4640                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4641                                 return true;
4642                         break;
4643                 case 6:
4644                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4645                                 return true;
4646                         break;
4647                 case 7:
4648                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4649                                 return true;
4650                         break;
4651                 }
4652         }
4653         return false;
4654 }
4655
4656 //==================================================================================
4657
4658 // LordHavoc: this stores temporary data used within the same frame
4659
4660 typedef struct r_framedata_mem_s
4661 {
4662         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4663         size_t size; // how much usable space
4664         size_t current; // how much space in use
4665         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4666         size_t wantedsize; // how much space was allocated
4667         unsigned char *data; // start of real data (16byte aligned)
4668 }
4669 r_framedata_mem_t;
4670
4671 static r_framedata_mem_t *r_framedata_mem;
4672
4673 void R_FrameData_Reset(void)
4674 {
4675         while (r_framedata_mem)
4676         {
4677                 r_framedata_mem_t *next = r_framedata_mem->purge;
4678                 Mem_Free(r_framedata_mem);
4679                 r_framedata_mem = next;
4680         }
4681 }
4682
4683 static void R_FrameData_Resize(qboolean mustgrow)
4684 {
4685         size_t wantedsize;
4686         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4687         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4688         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4689         {
4690                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4691                 newmem->wantedsize = wantedsize;
4692                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4693                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4694                 newmem->current = 0;
4695                 newmem->mark = 0;
4696                 newmem->purge = r_framedata_mem;
4697                 r_framedata_mem = newmem;
4698         }
4699 }
4700
4701 void R_FrameData_NewFrame(void)
4702 {
4703         R_FrameData_Resize(false);
4704         if (!r_framedata_mem)
4705                 return;
4706         // if we ran out of space on the last frame, free the old memory now
4707         while (r_framedata_mem->purge)
4708         {
4709                 // repeatedly remove the second item in the list, leaving only head
4710                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4711                 Mem_Free(r_framedata_mem->purge);
4712                 r_framedata_mem->purge = next;
4713         }
4714         // reset the current mem pointer
4715         r_framedata_mem->current = 0;
4716         r_framedata_mem->mark = 0;
4717 }
4718
4719 void *R_FrameData_Alloc(size_t size)
4720 {
4721         void *data;
4722         float newvalue;
4723
4724         // align to 16 byte boundary - the data pointer is already aligned, so we
4725         // only need to ensure the size of every allocation is also aligned
4726         size = (size + 15) & ~15;
4727
4728         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4729         {
4730                 // emergency - we ran out of space, allocate more memory
4731                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4732                 newvalue = r_framedatasize.value * 2.0f;
4733                 // 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
4734                 if (sizeof(size_t) >= 8)
4735                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4736                 else
4737                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4738                 // this might not be a growing it, but we'll allocate another buffer every time
4739                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4740                 R_FrameData_Resize(true);
4741         }
4742
4743         data = r_framedata_mem->data + r_framedata_mem->current;
4744         r_framedata_mem->current += size;
4745
4746         // count the usage for stats
4747         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4748         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4749
4750         return (void *)data;
4751 }
4752
4753 void *R_FrameData_Store(size_t size, void *data)
4754 {
4755         void *d = R_FrameData_Alloc(size);
4756         if (d && data)
4757                 memcpy(d, data, size);
4758         return d;
4759 }
4760
4761 void R_FrameData_SetMark(void)
4762 {
4763         if (!r_framedata_mem)
4764                 return;
4765         r_framedata_mem->mark = r_framedata_mem->current;
4766 }
4767
4768 void R_FrameData_ReturnToMark(void)
4769 {
4770         if (!r_framedata_mem)
4771                 return;
4772         r_framedata_mem->current = r_framedata_mem->mark;
4773 }
4774
4775 //==================================================================================
4776
4777 // avoid reusing the same buffer objects on consecutive frames
4778 #define R_BUFFERDATA_CYCLE 3
4779
4780 typedef struct r_bufferdata_buffer_s
4781 {
4782         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4783         size_t size; // how much usable space
4784         size_t current; // how much space in use
4785         r_meshbuffer_t *buffer; // the buffer itself
4786 }
4787 r_bufferdata_buffer_t;
4788
4789 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4790 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4791
4792 /// frees all dynamic buffers
4793 void R_BufferData_Reset(void)
4794 {
4795         int cycle, type;
4796         r_bufferdata_buffer_t **p, *mem;
4797         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4798         {
4799                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4800                 {
4801                         // free all buffers
4802                         p = &r_bufferdata_buffer[cycle][type];
4803                         while (*p)
4804                         {
4805                                 mem = *p;
4806                                 *p = (*p)->purge;
4807                                 if (mem->buffer)
4808                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4809                                 Mem_Free(mem);
4810                         }
4811                 }
4812         }
4813 }
4814
4815 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4816 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4817 {
4818         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4819         size_t size;
4820         float newvalue = r_buffermegs[type].value;
4821
4822         // increase the cvar if we have to (but only if we already have a mem)
4823         if (mustgrow && mem)
4824                 newvalue *= 2.0f;
4825         newvalue = bound(0.25f, newvalue, 256.0f);
4826         while (newvalue * 1024*1024 < minsize)
4827                 newvalue *= 2.0f;
4828
4829         // clamp the cvar to valid range
4830         newvalue = bound(0.25f, newvalue, 256.0f);
4831         if (r_buffermegs[type].value != newvalue)
4832                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4833
4834         // calculate size in bytes
4835         size = (size_t)(newvalue * 1024*1024);
4836         size = bound(131072, size, 256*1024*1024);
4837
4838         // allocate a new buffer if the size is different (purge old one later)
4839         // or if we were told we must grow the buffer
4840         if (!mem || mem->size != size || mustgrow)
4841         {
4842                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4843                 mem->size = size;
4844                 mem->current = 0;
4845                 if (type == R_BUFFERDATA_VERTEX)
4846                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4847                 else if (type == R_BUFFERDATA_INDEX16)
4848                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4849                 else if (type == R_BUFFERDATA_INDEX32)
4850                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4851                 else if (type == R_BUFFERDATA_UNIFORM)
4852                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4853                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4854                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4855         }
4856 }
4857
4858 void R_BufferData_NewFrame(void)
4859 {
4860         int type;
4861         r_bufferdata_buffer_t **p, *mem;
4862         // cycle to the next frame's buffers
4863         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4864         // if we ran out of space on the last time we used these buffers, free the old memory now
4865         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4866         {
4867                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4868                 {
4869                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4870                         // free all but the head buffer, this is how we recycle obsolete
4871                         // buffers after they are no longer in use
4872                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4873                         while (*p)
4874                         {
4875                                 mem = *p;
4876                                 *p = (*p)->purge;
4877                                 if (mem->buffer)
4878                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4879                                 Mem_Free(mem);
4880                         }
4881                         // reset the current offset
4882                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4883                 }
4884         }
4885 }
4886
4887 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4888 {
4889         r_bufferdata_buffer_t *mem;
4890         int offset = 0;
4891         int padsize;
4892
4893         *returnbufferoffset = 0;
4894
4895         // align size to a byte boundary appropriate for the buffer type, this
4896         // makes all allocations have aligned start offsets
4897         if (type == R_BUFFERDATA_UNIFORM)
4898                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4899         else
4900                 padsize = (datasize + 15) & ~15;
4901
4902         // if we ran out of space in this buffer we must allocate a new one
4903         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)
4904                 R_BufferData_Resize(type, true, padsize);
4905
4906         // if the resize did not give us enough memory, fail
4907         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)
4908                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4909
4910         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4911         offset = (int)mem->current;
4912         mem->current += padsize;
4913
4914         // upload the data to the buffer at the chosen offset
4915         if (offset == 0)
4916                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4917         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4918
4919         // count the usage for stats
4920         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4921         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4922
4923         // return the buffer offset
4924         *returnbufferoffset = offset;
4925
4926         return mem->buffer;
4927 }
4928
4929 //==================================================================================
4930
4931 // LordHavoc: animcache originally written by Echon, rewritten since then
4932
4933 /**
4934  * Animation cache prevents re-generating mesh data for an animated model
4935  * multiple times in one frame for lighting, shadowing, reflections, etc.
4936  */
4937
4938 void R_AnimCache_Free(void)
4939 {
4940 }
4941
4942 void R_AnimCache_ClearCache(void)
4943 {
4944         int i;
4945         entity_render_t *ent;
4946
4947         for (i = 0;i < r_refdef.scene.numentities;i++)
4948         {
4949                 ent = r_refdef.scene.entities[i];
4950                 ent->animcache_vertex3f = NULL;
4951                 ent->animcache_vertex3f_vertexbuffer = NULL;
4952                 ent->animcache_vertex3f_bufferoffset = 0;
4953                 ent->animcache_normal3f = NULL;
4954                 ent->animcache_normal3f_vertexbuffer = NULL;
4955                 ent->animcache_normal3f_bufferoffset = 0;
4956                 ent->animcache_svector3f = NULL;
4957                 ent->animcache_svector3f_vertexbuffer = NULL;
4958                 ent->animcache_svector3f_bufferoffset = 0;
4959                 ent->animcache_tvector3f = NULL;
4960                 ent->animcache_tvector3f_vertexbuffer = NULL;
4961                 ent->animcache_tvector3f_bufferoffset = 0;
4962                 ent->animcache_vertexmesh = NULL;
4963                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4964                 ent->animcache_vertexmesh_bufferoffset = 0;
4965                 ent->animcache_skeletaltransform3x4 = NULL;
4966                 ent->animcache_skeletaltransform3x4buffer = NULL;
4967                 ent->animcache_skeletaltransform3x4offset = 0;
4968                 ent->animcache_skeletaltransform3x4size = 0;
4969         }
4970 }
4971
4972 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4973 {
4974         int i;
4975
4976         // check if we need the meshbuffers
4977         if (!vid.useinterleavedarrays)
4978                 return;
4979
4980         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4981                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4982         // TODO: upload vertexbuffer?
4983         if (ent->animcache_vertexmesh)
4984         {
4985                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4986                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4987                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4988                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4989                 for (i = 0;i < numvertices;i++)
4990                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4991                 if (ent->animcache_svector3f)
4992                         for (i = 0;i < numvertices;i++)
4993                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4994                 if (ent->animcache_tvector3f)
4995                         for (i = 0;i < numvertices;i++)
4996                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4997                 if (ent->animcache_normal3f)
4998                         for (i = 0;i < numvertices;i++)
4999                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
5000         }
5001 }
5002
5003 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5004 {
5005         dp_model_t *model = ent->model;
5006         int numvertices;
5007
5008         // see if this ent is worth caching
5009         if (!model || !model->Draw || !model->AnimateVertices)
5010                 return false;
5011         // nothing to cache if it contains no animations and has no skeleton
5012         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5013                 return false;
5014         // see if it is already cached for gpuskeletal
5015         if (ent->animcache_skeletaltransform3x4)
5016                 return false;
5017         // see if it is already cached as a mesh
5018         if (ent->animcache_vertex3f)
5019         {
5020                 // check if we need to add normals or tangents
5021                 if (ent->animcache_normal3f)
5022                         wantnormals = false;
5023                 if (ent->animcache_svector3f)
5024                         wanttangents = false;
5025                 if (!wantnormals && !wanttangents)
5026                         return false;
5027         }
5028
5029         // check which kind of cache we need to generate
5030         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5031         {
5032                 // cache the skeleton so the vertex shader can use it
5033                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5034                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5035                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5036                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5037                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5038                 // note: this can fail if the buffer is at the grow limit
5039                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5040                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5041         }
5042         else if (ent->animcache_vertex3f)
5043         {
5044                 // mesh was already cached but we may need to add normals/tangents
5045                 // (this only happens with multiple views, reflections, cameras, etc)
5046                 if (wantnormals || wanttangents)
5047                 {
5048                         numvertices = model->surfmesh.num_vertices;
5049                         if (wantnormals)
5050                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5051                         if (wanttangents)
5052                         {
5053                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5054                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5055                         }
5056                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5057                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5058                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5059                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5060                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5061                 }
5062         }
5063         else
5064         {
5065                 // generate mesh cache
5066                 numvertices = model->surfmesh.num_vertices;
5067                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5068                 if (wantnormals)
5069                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5070                 if (wanttangents)
5071                 {
5072                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5073                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5074                 }
5075                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5076                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5077                 if (wantnormals || wanttangents)
5078                 {
5079                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5080                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5081                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5082                 }
5083                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5084                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5085                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5086         }
5087         return true;
5088 }
5089
5090 void R_AnimCache_CacheVisibleEntities(void)
5091 {
5092         int i;
5093         qboolean wantnormals = true;
5094         qboolean wanttangents = !r_showsurfaces.integer;
5095
5096         switch(vid.renderpath)
5097         {
5098         case RENDERPATH_GL20:
5099         case RENDERPATH_D3D9:
5100         case RENDERPATH_D3D10:
5101         case RENDERPATH_D3D11:
5102         case RENDERPATH_GLES2:
5103                 break;
5104         case RENDERPATH_GL11:
5105         case RENDERPATH_GL13:
5106         case RENDERPATH_GLES1:
5107                 wanttangents = false;
5108                 break;
5109         case RENDERPATH_SOFT:
5110                 break;
5111         }
5112
5113         if (r_shownormals.integer)
5114                 wanttangents = wantnormals = true;
5115
5116         // TODO: thread this
5117         // NOTE: R_PrepareRTLights() also caches entities
5118
5119         for (i = 0;i < r_refdef.scene.numentities;i++)
5120                 if (r_refdef.viewcache.entityvisible[i])
5121                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5122 }
5123
5124 //==================================================================================
5125
5126 extern cvar_t r_overheadsprites_pushback;
5127
5128 static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
5129 {
5130         vec3_t angles;
5131
5132         VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
5133         VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
5134
5135         // Use cl.viewangles and not r_refdef.view.forward here so it is the
5136         // same for all stereo views, and to better handle pitches outside
5137         // [-90, 90] (in_pitch_* cvars allow that).
5138         VectorCopy(cl.viewangles, angles);
5139         if (r_fullbright_directed_pitch_relative.integer) {
5140                 angles[PITCH] += r_fullbright_directed_pitch.value;
5141         } else {
5142                 angles[PITCH] = r_fullbright_directed_pitch.value;
5143         }
5144         AngleVectors(angles, worldspacenormal, NULL, NULL);
5145         VectorNegate(worldspacenormal, worldspacenormal);
5146 }
5147
5148 static void R_View_UpdateEntityLighting (void)
5149 {
5150         int i;
5151         entity_render_t *ent;
5152         vec3_t tempdiffusenormal, avg;
5153         vec_t f, fa, fd, fdd;
5154         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5155
5156         for (i = 0;i < r_refdef.scene.numentities;i++)
5157         {
5158                 ent = r_refdef.scene.entities[i];
5159
5160                 // skip unseen models
5161                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5162                         continue;
5163
5164                 // skip bsp models
5165                 if (ent->model && ent->model == cl.worldmodel)
5166                 {
5167                         // TODO: use modellight for r_ambient settings on world?
5168                         // The logic here currently matches RSurf_ActiveWorldEntity.
5169                         if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit))
5170                         {
5171                                 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5172                                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5173                                 if(VectorLength2(ent->modellight_lightdir) == 0)
5174                                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5175                                 VectorNormalize(ent->modellight_lightdir);
5176                         }
5177                         else
5178                         {
5179                                 VectorSet(ent->modellight_ambient, 0, 0, 0);
5180                                 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5181                                 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5182                         }
5183                         continue;
5184                 }
5185                 
5186                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5187                 {
5188                         // aleady updated by CSQC
5189                         // TODO: force modellight on BSP models in this case?
5190                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5191                 }
5192                 else
5193                 {
5194                         // fetch the lighting from the worldmodel data
5195                         VectorClear(ent->modellight_ambient);
5196                         VectorClear(ent->modellight_diffuse);
5197                         VectorClear(tempdiffusenormal);
5198                         if (ent->flags & RENDER_LIGHT)
5199                         {
5200                                 vec3_t org;
5201                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5202
5203                                 // complete lightning for lit sprites
5204                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5205                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5206                                 {
5207                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5208                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5209                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5210                                 }
5211                                 else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
5212                                 {
5213                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5214                                 }
5215                                 else if (r_fullbright_directed.integer)
5216                                 {
5217                                         R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5218                                 }
5219                                 else
5220                                 {
5221                                         VectorSet(ent->modellight_ambient, 1, 1, 1);
5222                                 }
5223
5224                                 if(ent->flags & RENDER_EQUALIZE)
5225                                 {
5226                                         // first fix up ambient lighting...
5227                                         if(r_equalize_entities_minambient.value > 0)
5228                                         {
5229                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5230                                                 if(fd > 0)
5231                                                 {
5232                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5233                                                         if(fa < r_equalize_entities_minambient.value * fd)
5234                                                         {
5235                                                                 // solve:
5236                                                                 //   fa'/fd' = minambient
5237                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5238                                                                 //   ...
5239                                                                 //   fa' = fd' * minambient
5240                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5241                                                                 //   ...
5242                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5243                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5244                                                                 //   ...
5245                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5246                                                                 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
5247                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5248                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5249                                                         }
5250                                                 }
5251                                         }
5252
5253                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5254                                         {
5255                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5256                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5257                                                 f = fa + 0.25 * fd;
5258                                                 if(f > 0)
5259                                                 {
5260                                                         // adjust brightness and saturation to target
5261                                                         avg[0] = avg[1] = avg[2] = fa / f;
5262                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5263                                                         avg[0] = avg[1] = avg[2] = fd / f;
5264                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5265                                                 }
5266                                         }
5267                                 }
5268                         }
5269                         else
5270                         {
5271                                 // EF_FULLBRIGHT entity.
5272                                 if (r_fullbright_directed.integer)
5273                                 {
5274                                         R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5275                                 }
5276                                 else
5277                                 {
5278                                         VectorSet(ent->modellight_ambient, 1, 1, 1);
5279                                 }
5280                         }
5281                 }
5282
5283                 // move the light direction into modelspace coordinates for lighting code
5284                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5285                 if(VectorLength2(ent->modellight_lightdir) == 0)
5286                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5287                 VectorNormalize(ent->modellight_lightdir);
5288         }
5289 }
5290
5291 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5292 {
5293         int i;
5294         vec3_t eyemins, eyemaxs;
5295         vec3_t boxmins, boxmaxs;
5296         vec3_t start;
5297         vec3_t end;
5298         dp_model_t *model = r_refdef.scene.worldmodel;
5299         static vec3_t positions[] = {
5300                 { 0.5f, 0.5f, 0.5f },
5301                 { 0.0f, 0.0f, 0.0f },
5302                 { 0.0f, 0.0f, 1.0f },
5303                 { 0.0f, 1.0f, 0.0f },
5304                 { 0.0f, 1.0f, 1.0f },
5305                 { 1.0f, 0.0f, 0.0f },
5306                 { 1.0f, 0.0f, 1.0f },
5307                 { 1.0f, 1.0f, 0.0f },
5308                 { 1.0f, 1.0f, 1.0f },
5309         };
5310
5311         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5312         if (numsamples < 0)
5313                 return true;
5314
5315         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5316         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5317                 return true;
5318
5319         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5320                 return true;
5321
5322         // expand the eye box a little
5323         eyemins[0] = eye[0] - eyejitter;
5324         eyemaxs[0] = eye[0] + eyejitter;
5325         eyemins[1] = eye[1] - eyejitter;
5326         eyemaxs[1] = eye[1] + eyejitter;
5327         eyemins[2] = eye[2] - eyejitter;
5328         eyemaxs[2] = eye[2] + eyejitter;
5329         // expand the box a little
5330         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5331         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5332         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5333         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5334         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5335         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5336
5337         // return true if eye overlaps enlarged box
5338         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5339                 return true;
5340
5341         // try specific positions in the box first - note that these can be cached
5342         if (r_cullentities_trace_entityocclusion.integer)
5343         {
5344                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5345                 {
5346                         VectorCopy(eye, start);
5347                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5348                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5349                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5350                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5351                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5352                         // not picky - if the trace ended anywhere in the box we're good
5353                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5354                                 return true;
5355                 }
5356         }
5357         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5358                 return true;
5359
5360         // try various random positions
5361         for (i = 0; i < numsamples; i++)
5362         {
5363                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5364                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5365                 if (r_cullentities_trace_entityocclusion.integer)
5366                 {
5367                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5368                         // not picky - if the trace ended anywhere in the box we're good
5369                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5370                                 return true;
5371                 }
5372                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5373                         return true;
5374         }
5375
5376         return false;
5377 }
5378
5379
5380 static void R_View_UpdateEntityVisible (void)
5381 {
5382         int i;
5383         int renderimask;
5384         int samples;
5385         entity_render_t *ent;
5386
5387         if (r_refdef.envmap || r_fb.water.hideplayer)
5388                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5389         else if (chase_active.integer || r_fb.water.renderingscene)
5390                 renderimask = RENDER_VIEWMODEL;
5391         else
5392                 renderimask = RENDER_EXTERIORMODEL;
5393         if (!r_drawviewmodel.integer)
5394                 renderimask |= RENDER_VIEWMODEL;
5395         if (!r_drawexteriormodel.integer)
5396                 renderimask |= RENDER_EXTERIORMODEL;
5397         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5398         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5399         {
5400                 // worldmodel can 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                         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))
5407                                 r_refdef.viewcache.entityvisible[i] = true;
5408                 }
5409         }
5410         else
5411         {
5412                 // no worldmodel or it can't check visibility
5413                 for (i = 0;i < r_refdef.scene.numentities;i++)
5414                 {
5415                         ent = r_refdef.scene.entities[i];
5416                         if (!(ent->flags & renderimask))
5417                         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)))
5418                                 r_refdef.viewcache.entityvisible[i] = true;
5419                 }
5420         }
5421         if (r_cullentities_trace.integer)
5422         {
5423                 for (i = 0;i < r_refdef.scene.numentities;i++)
5424                 {
5425                         if (!r_refdef.viewcache.entityvisible[i])
5426                                 continue;
5427                         ent = r_refdef.scene.entities[i];
5428                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5429                         {
5430                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5431                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5432                                         ent->last_trace_visibility = realtime;
5433                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5434                                         r_refdef.viewcache.entityvisible[i] = 0;
5435                         }
5436                 }
5437         }
5438 }
5439
5440 /// only used if skyrendermasked, and normally returns false
5441 static int R_DrawBrushModelsSky (void)
5442 {
5443         int i, sky;
5444         entity_render_t *ent;
5445
5446         sky = false;
5447         for (i = 0;i < r_refdef.scene.numentities;i++)
5448         {
5449                 if (!r_refdef.viewcache.entityvisible[i])
5450                         continue;
5451                 ent = r_refdef.scene.entities[i];
5452                 if (!ent->model || !ent->model->DrawSky)
5453                         continue;
5454                 ent->model->DrawSky(ent);
5455                 sky = true;
5456         }
5457         return sky;
5458 }
5459
5460 static void R_DrawNoModel(entity_render_t *ent);
5461 static void R_DrawModels(void)
5462 {
5463         int i;
5464         entity_render_t *ent;
5465
5466         for (i = 0;i < r_refdef.scene.numentities;i++)
5467         {
5468                 if (!r_refdef.viewcache.entityvisible[i])
5469                         continue;
5470                 ent = r_refdef.scene.entities[i];
5471                 r_refdef.stats[r_stat_entities]++;
5472                 /*
5473                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5474                 {
5475                         vec3_t f, l, u, o;
5476                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5477                         Con_Printf("R_DrawModels\n");
5478                         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]);
5479                         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);
5480                         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);
5481                 }
5482                 */
5483                 if (ent->model && ent->model->Draw != NULL)
5484                         ent->model->Draw(ent);
5485                 else
5486                         R_DrawNoModel(ent);
5487         }
5488 }
5489
5490 static void R_DrawModelsDepth(void)
5491 {
5492         int i;
5493         entity_render_t *ent;
5494
5495         for (i = 0;i < r_refdef.scene.numentities;i++)
5496         {
5497                 if (!r_refdef.viewcache.entityvisible[i])
5498                         continue;
5499                 ent = r_refdef.scene.entities[i];
5500                 if (ent->model && ent->model->DrawDepth != NULL)
5501                         ent->model->DrawDepth(ent);
5502         }
5503 }
5504
5505 static void R_DrawModelsDebug(void)
5506 {
5507         int i;
5508         entity_render_t *ent;
5509
5510         for (i = 0;i < r_refdef.scene.numentities;i++)
5511         {
5512                 if (!r_refdef.viewcache.entityvisible[i])
5513                         continue;
5514                 ent = r_refdef.scene.entities[i];
5515                 if (ent->model && ent->model->DrawDebug != NULL)
5516                         ent->model->DrawDebug(ent);
5517         }
5518 }
5519
5520 static void R_DrawModelsAddWaterPlanes(void)
5521 {
5522         int i;
5523         entity_render_t *ent;
5524
5525         for (i = 0;i < r_refdef.scene.numentities;i++)
5526         {
5527                 if (!r_refdef.viewcache.entityvisible[i])
5528                         continue;
5529                 ent = r_refdef.scene.entities[i];
5530                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5531                         ent->model->DrawAddWaterPlanes(ent);
5532         }
5533 }
5534
5535 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}};
5536
5537 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5538 {
5539         if (r_hdr_irisadaptation.integer)
5540         {
5541                 vec3_t p;
5542                 vec3_t ambient;
5543                 vec3_t diffuse;
5544                 vec3_t diffusenormal;
5545                 vec3_t forward;
5546                 vec_t brightness = 0.0f;
5547                 vec_t goal;
5548                 vec_t current;
5549                 vec_t d;
5550                 int c;
5551                 VectorCopy(r_refdef.view.forward, forward);
5552                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5553                 {
5554                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5555                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5556                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5557                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5558                         d = DotProduct(forward, diffusenormal);
5559                         brightness += VectorLength(ambient);
5560                         if (d > 0)
5561                                 brightness += d * VectorLength(diffuse);
5562                 }
5563                 brightness *= 1.0f / c;
5564                 brightness += 0.00001f; // make sure it's never zero
5565                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5566                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5567                 current = r_hdr_irisadaptation_value.value;
5568                 if (current < goal)
5569                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5570                 else if (current > goal)
5571                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5572                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5573                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5574         }
5575         else if (r_hdr_irisadaptation_value.value != 1.0f)
5576                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5577 }
5578
5579 static void R_View_SetFrustum(const int *scissor)
5580 {
5581         int i;
5582         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5583         vec3_t forward, left, up, origin, v;
5584
5585         if(scissor)
5586         {
5587                 // flipped x coordinates (because x points left here)
5588                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5589                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5590
5591                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5592                 switch(vid.renderpath)
5593                 {
5594                         case RENDERPATH_D3D9:
5595                         case RENDERPATH_D3D10:
5596                         case RENDERPATH_D3D11:
5597                                 // non-flipped y coordinates
5598                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5599                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5600                                 break;
5601                         case RENDERPATH_SOFT:
5602                         case RENDERPATH_GL11:
5603                         case RENDERPATH_GL13:
5604                         case RENDERPATH_GL20:
5605                         case RENDERPATH_GLES1:
5606                         case RENDERPATH_GLES2:
5607                                 // non-flipped y coordinates
5608                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5609                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5610                                 break;
5611                 }
5612         }
5613
5614         // we can't trust r_refdef.view.forward and friends in reflected scenes
5615         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5616
5617 #if 0
5618         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5619         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5620         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5621         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5622         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5623         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5624         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5625         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5626         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5627         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5628         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5629         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5630 #endif
5631
5632 #if 0
5633         zNear = r_refdef.nearclip;
5634         nudge = 1.0 - 1.0 / (1<<23);
5635         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5636         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5637         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5638         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5639         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5640         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5641         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5642         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5643 #endif
5644
5645
5646
5647 #if 0
5648         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5649         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5650         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5651         r_refdef.view.frustum[0].dist = m[15] - m[12];
5652
5653         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5654         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5655         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5656         r_refdef.view.frustum[1].dist = m[15] + m[12];
5657
5658         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5659         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5660         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5661         r_refdef.view.frustum[2].dist = m[15] - m[13];
5662
5663         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5664         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5665         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5666         r_refdef.view.frustum[3].dist = m[15] + m[13];
5667
5668         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5669         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5670         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5671         r_refdef.view.frustum[4].dist = m[15] - m[14];
5672
5673         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5674         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5675         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5676         r_refdef.view.frustum[5].dist = m[15] + m[14];
5677 #endif
5678
5679         if (r_refdef.view.useperspective)
5680         {
5681                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5682                 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]);
5683                 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]);
5684                 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]);
5685                 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]);
5686
5687                 // then the normals from the corners relative to origin
5688                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5689                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5690                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5691                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5692
5693                 // in a NORMAL view, forward cross left == up
5694                 // in a REFLECTED view, forward cross left == down
5695                 // so our cross products above need to be adjusted for a left handed coordinate system
5696                 CrossProduct(forward, left, v);
5697                 if(DotProduct(v, up) < 0)
5698                 {
5699                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5700                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5701                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5702                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5703                 }
5704
5705                 // Leaving those out was a mistake, those were in the old code, and they
5706                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5707                 // I couldn't reproduce it after adding those normalizations. --blub
5708                 VectorNormalize(r_refdef.view.frustum[0].normal);
5709                 VectorNormalize(r_refdef.view.frustum[1].normal);
5710                 VectorNormalize(r_refdef.view.frustum[2].normal);
5711                 VectorNormalize(r_refdef.view.frustum[3].normal);
5712
5713                 // make the corners absolute
5714                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5715                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5716                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5717                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5718
5719                 // one more normal
5720                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5721
5722                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5723                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5724                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5725                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5726                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5727         }
5728         else
5729         {
5730                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5731                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5732                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5733                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5734                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5735                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5736                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5737                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5738                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5739                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5740         }
5741         r_refdef.view.numfrustumplanes = 5;
5742
5743         if (r_refdef.view.useclipplane)
5744         {
5745                 r_refdef.view.numfrustumplanes = 6;
5746                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5747         }
5748
5749         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5750                 PlaneClassify(r_refdef.view.frustum + i);
5751
5752         // LordHavoc: note to all quake engine coders, Quake had a special case
5753         // for 90 degrees which assumed a square view (wrong), so I removed it,
5754         // Quake2 has it disabled as well.
5755
5756         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5757         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5758         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5759         //PlaneClassify(&frustum[0]);
5760
5761         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5762         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5763         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5764         //PlaneClassify(&frustum[1]);
5765
5766         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5767         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5768         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5769         //PlaneClassify(&frustum[2]);
5770
5771         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5772         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5773         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5774         //PlaneClassify(&frustum[3]);
5775
5776         // nearclip plane
5777         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5778         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5779         //PlaneClassify(&frustum[4]);
5780 }
5781
5782 static void R_View_UpdateWithScissor(const int *myscissor)
5783 {
5784         R_Main_ResizeViewCache();
5785         R_View_SetFrustum(myscissor);
5786         R_View_WorldVisibility(r_refdef.view.useclipplane);
5787         R_View_UpdateEntityVisible();
5788         R_View_UpdateEntityLighting();
5789 }
5790
5791 static void R_View_Update(void)
5792 {
5793         R_Main_ResizeViewCache();
5794         R_View_SetFrustum(NULL);
5795         R_View_WorldVisibility(r_refdef.view.useclipplane);
5796         R_View_UpdateEntityVisible();
5797         R_View_UpdateEntityLighting();
5798 }
5799
5800 float viewscalefpsadjusted = 1.0f;
5801
5802 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5803 {
5804         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5805         scale = bound(0.03125f, scale, 1.0f);
5806         *outwidth = (int)ceil(width * scale);
5807         *outheight = (int)ceil(height * scale);
5808 }
5809
5810 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5811 {
5812         const float *customclipplane = NULL;
5813         float plane[4];
5814         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5815         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5816         {
5817                 // LordHavoc: couldn't figure out how to make this approach the
5818                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5819                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5820                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5821                         dist = r_refdef.view.clipplane.dist;
5822                 plane[0] = r_refdef.view.clipplane.normal[0];
5823                 plane[1] = r_refdef.view.clipplane.normal[1];
5824                 plane[2] = r_refdef.view.clipplane.normal[2];
5825                 plane[3] = -dist;
5826                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5827         }
5828
5829         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5830         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5831
5832         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5833         if (!r_refdef.view.useperspective)
5834                 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);
5835         else if (vid.stencil && r_useinfinitefarclip.integer)
5836                 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);
5837         else
5838                 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);
5839         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5840         R_SetViewport(&r_refdef.view.viewport);
5841         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5842         {
5843                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5844                 float screenplane[4];
5845                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5846                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5847                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5848                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5849                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5850         }
5851 }
5852
5853 void R_EntityMatrix(const matrix4x4_t *matrix)
5854 {
5855         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5856         {
5857                 gl_modelmatrixchanged = false;
5858                 gl_modelmatrix = *matrix;
5859                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5860                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5861                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5862                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5863                 CHECKGLERROR
5864                 switch(vid.renderpath)
5865                 {
5866                 case RENDERPATH_D3D9:
5867 #ifdef SUPPORTD3D
5868                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5869                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5870 #endif
5871                         break;
5872                 case RENDERPATH_D3D10:
5873                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5874                         break;
5875                 case RENDERPATH_D3D11:
5876                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5877                         break;
5878                 case RENDERPATH_GL11:
5879                 case RENDERPATH_GL13:
5880                 case RENDERPATH_GLES1:
5881 #ifndef USE_GLES2
5882                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5883 #endif
5884                         break;
5885                 case RENDERPATH_SOFT:
5886                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5887                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5888                         break;
5889                 case RENDERPATH_GL20:
5890                 case RENDERPATH_GLES2:
5891                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5892                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5893                         break;
5894                 }
5895         }
5896 }
5897
5898 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5899 {
5900         r_viewport_t viewport;
5901
5902         CHECKGLERROR
5903
5904         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5905         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);
5906         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5907         R_SetViewport(&viewport);
5908         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5909         GL_Color(1, 1, 1, 1);
5910         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5911         GL_BlendFunc(GL_ONE, GL_ZERO);
5912         GL_ScissorTest(false);
5913         GL_DepthMask(false);
5914         GL_DepthRange(0, 1);
5915         GL_DepthTest(false);
5916         GL_DepthFunc(GL_LEQUAL);
5917         R_EntityMatrix(&identitymatrix);
5918         R_Mesh_ResetTextureState();
5919         GL_PolygonOffset(0, 0);
5920         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5921         switch(vid.renderpath)
5922         {
5923         case RENDERPATH_GL11:
5924         case RENDERPATH_GL13:
5925         case RENDERPATH_GL20:
5926         case RENDERPATH_GLES1:
5927         case RENDERPATH_GLES2:
5928                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5929                 break;
5930         case RENDERPATH_D3D9:
5931         case RENDERPATH_D3D10:
5932         case RENDERPATH_D3D11:
5933         case RENDERPATH_SOFT:
5934                 break;
5935         }
5936         GL_CullFace(GL_NONE);
5937
5938         CHECKGLERROR
5939 }
5940
5941 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5942 {
5943         DrawQ_Finish();
5944
5945         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5946 }
5947
5948 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5949 {
5950         DrawQ_Finish();
5951
5952         R_SetupView(true, fbo, depthtexture, colortexture);
5953         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5954         GL_Color(1, 1, 1, 1);
5955         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5956         GL_BlendFunc(GL_ONE, GL_ZERO);
5957         GL_ScissorTest(true);
5958         GL_DepthMask(true);
5959         GL_DepthRange(0, 1);
5960         GL_DepthTest(true);
5961         GL_DepthFunc(GL_LEQUAL);
5962         R_EntityMatrix(&identitymatrix);
5963         R_Mesh_ResetTextureState();
5964         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5965         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5966         switch(vid.renderpath)
5967         {
5968         case RENDERPATH_GL11:
5969         case RENDERPATH_GL13:
5970         case RENDERPATH_GL20:
5971         case RENDERPATH_GLES1:
5972         case RENDERPATH_GLES2:
5973                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5974                 break;
5975         case RENDERPATH_D3D9:
5976         case RENDERPATH_D3D10:
5977         case RENDERPATH_D3D11:
5978         case RENDERPATH_SOFT:
5979                 break;
5980         }
5981         GL_CullFace(r_refdef.view.cullface_back);
5982 }
5983
5984 /*
5985 ================
5986 R_RenderView_UpdateViewVectors
5987 ================
5988 */
5989 void R_RenderView_UpdateViewVectors(void)
5990 {
5991         // break apart the view matrix into vectors for various purposes
5992         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5993         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5994         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5995         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5996         // make an inverted copy of the view matrix for tracking sprites
5997         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5998 }
5999
6000 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6001 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6002
6003 static void R_Water_StartFrame(void)
6004 {
6005         int i;
6006         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
6007         r_waterstate_waterplane_t *p;
6008         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;
6009
6010         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6011                 return;
6012
6013         switch(vid.renderpath)
6014         {
6015         case RENDERPATH_GL20:
6016         case RENDERPATH_D3D9:
6017         case RENDERPATH_D3D10:
6018         case RENDERPATH_D3D11:
6019         case RENDERPATH_SOFT:
6020         case RENDERPATH_GLES2:
6021                 break;
6022         case RENDERPATH_GL11:
6023         case RENDERPATH_GL13:
6024         case RENDERPATH_GLES1:
6025                 return;
6026         }
6027
6028         // set waterwidth and waterheight to the water resolution that will be
6029         // used (often less than the screen resolution for faster rendering)
6030         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
6031
6032         // calculate desired texture sizes
6033         // can't use water if the card does not support the texture size
6034         if (!r_water.integer || r_showsurfaces.integer)
6035                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
6036         else if (vid.support.arb_texture_non_power_of_two)
6037         {
6038                 texturewidth = waterwidth;
6039                 textureheight = waterheight;
6040                 camerawidth = waterwidth;
6041                 cameraheight = waterheight;
6042         }
6043         else
6044         {
6045                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
6046                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
6047                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
6048                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
6049         }
6050
6051         // allocate textures as needed
6052         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))
6053         {
6054                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6055                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
6056                 {
6057                         if (p->texture_refraction)
6058                                 R_FreeTexture(p->texture_refraction);
6059                         p->texture_refraction = NULL;
6060                         if (p->fbo_refraction)
6061                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
6062                         p->fbo_refraction = 0;
6063                         if (p->texture_reflection)
6064                                 R_FreeTexture(p->texture_reflection);
6065                         p->texture_reflection = NULL;
6066                         if (p->fbo_reflection)
6067                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6068                         p->fbo_reflection = 0;
6069                         if (p->texture_camera)
6070                                 R_FreeTexture(p->texture_camera);
6071                         p->texture_camera = NULL;
6072                         if (p->fbo_camera)
6073                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6074                         p->fbo_camera = 0;
6075                 }
6076                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6077                 r_fb.water.texturewidth = texturewidth;
6078                 r_fb.water.textureheight = textureheight;
6079                 r_fb.water.camerawidth = camerawidth;
6080                 r_fb.water.cameraheight = cameraheight;
6081         }
6082
6083         if (r_fb.water.texturewidth)
6084         {
6085                 int scaledwidth, scaledheight;
6086
6087                 r_fb.water.enabled = true;
6088
6089                 // water resolution is usually reduced
6090                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6091                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6092                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6093
6094                 // set up variables that will be used in shader setup
6095                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6096                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6097                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6098                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6099         }
6100
6101         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6102         r_fb.water.numwaterplanes = 0;
6103 }
6104
6105 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6106 {
6107         int planeindex, bestplaneindex, vertexindex;
6108         vec3_t mins, maxs, normal, center, v, n;
6109         vec_t planescore, bestplanescore;
6110         mplane_t plane;
6111         r_waterstate_waterplane_t *p;
6112         texture_t *t = R_GetCurrentTexture(surface->texture);
6113
6114         rsurface.texture = t;
6115         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6116         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6117         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6118                 return;
6119         // average the vertex normals, find the surface bounds (after deformvertexes)
6120         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6121         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6122         VectorCopy(n, normal);
6123         VectorCopy(v, mins);
6124         VectorCopy(v, maxs);
6125         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6126         {
6127                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6128                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6129                 VectorAdd(normal, n, normal);
6130                 mins[0] = min(mins[0], v[0]);
6131                 mins[1] = min(mins[1], v[1]);
6132                 mins[2] = min(mins[2], v[2]);
6133                 maxs[0] = max(maxs[0], v[0]);
6134                 maxs[1] = max(maxs[1], v[1]);
6135                 maxs[2] = max(maxs[2], v[2]);
6136         }
6137         VectorNormalize(normal);
6138         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6139
6140         VectorCopy(normal, plane.normal);
6141         VectorNormalize(plane.normal);
6142         plane.dist = DotProduct(center, plane.normal);
6143         PlaneClassify(&plane);
6144         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6145         {
6146                 // skip backfaces (except if nocullface is set)
6147 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6148 //                      return;
6149                 VectorNegate(plane.normal, plane.normal);
6150                 plane.dist *= -1;
6151                 PlaneClassify(&plane);
6152         }
6153
6154
6155         // find a matching plane if there is one
6156         bestplaneindex = -1;
6157         bestplanescore = 1048576.0f;
6158         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6159         {
6160                 if(p->camera_entity == t->camera_entity)
6161                 {
6162                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6163                         if (bestplaneindex < 0 || bestplanescore > planescore)
6164                         {
6165                                 bestplaneindex = planeindex;
6166                                 bestplanescore = planescore;
6167                         }
6168                 }
6169         }
6170         planeindex = bestplaneindex;
6171
6172         // if this surface does not fit any known plane rendered this frame, add one
6173         if (planeindex < 0 || bestplanescore > 0.001f)
6174         {
6175                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6176                 {
6177                         // store the new plane
6178                         planeindex = r_fb.water.numwaterplanes++;
6179                         p = r_fb.water.waterplanes + planeindex;
6180                         p->plane = plane;
6181                         // clear materialflags and pvs
6182                         p->materialflags = 0;
6183                         p->pvsvalid = false;
6184                         p->camera_entity = t->camera_entity;
6185                         VectorCopy(mins, p->mins);
6186                         VectorCopy(maxs, p->maxs);
6187                 }
6188                 else
6189                 {
6190                         // We're totally screwed.
6191                         return;
6192                 }
6193         }
6194         else
6195         {
6196                 // merge mins/maxs when we're adding this surface to the plane
6197                 p = r_fb.water.waterplanes + planeindex;
6198                 p->mins[0] = min(p->mins[0], mins[0]);
6199                 p->mins[1] = min(p->mins[1], mins[1]);
6200                 p->mins[2] = min(p->mins[2], mins[2]);
6201                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6202                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6203                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6204         }
6205         // merge this surface's materialflags into the waterplane
6206         p->materialflags |= t->currentmaterialflags;
6207         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6208         {
6209                 // merge this surface's PVS into the waterplane
6210                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6211                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6212                 {
6213                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6214                         p->pvsvalid = true;
6215                 }
6216         }
6217 }
6218
6219 extern cvar_t r_drawparticles;
6220 extern cvar_t r_drawdecals;
6221
6222 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6223 {
6224         int myscissor[4];
6225         r_refdef_view_t originalview;
6226         r_refdef_view_t myview;
6227         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;
6228         r_waterstate_waterplane_t *p;
6229         vec3_t visorigin;
6230         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;
6231         char vabuf[1024];
6232
6233         originalview = r_refdef.view;
6234
6235         // lowquality hack, temporarily shut down some cvars and restore afterwards
6236         qualityreduction = r_water_lowquality.integer;
6237         if (qualityreduction > 0)
6238         {
6239                 if (qualityreduction >= 1)
6240                 {
6241                         old_r_shadows = r_shadows.integer;
6242                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6243                         old_r_dlight = r_shadow_realtime_dlight.integer;
6244                         Cvar_SetValueQuick(&r_shadows, 0);
6245                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6246                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6247                 }
6248                 if (qualityreduction >= 2)
6249                 {
6250                         old_r_dynamic = r_dynamic.integer;
6251                         old_r_particles = r_drawparticles.integer;
6252                         old_r_decals = r_drawdecals.integer;
6253                         Cvar_SetValueQuick(&r_dynamic, 0);
6254                         Cvar_SetValueQuick(&r_drawparticles, 0);
6255                         Cvar_SetValueQuick(&r_drawdecals, 0);
6256                 }
6257         }
6258
6259         // make sure enough textures are allocated
6260         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6261         {
6262                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6263                         continue;
6264                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6265                 {
6266                         if (!p->texture_refraction)
6267                                 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);
6268                         if (!p->texture_refraction)
6269                                 goto error;
6270                         if (usewaterfbo)
6271                         {
6272                                 if (r_fb.water.depthtexture == NULL)
6273                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6274                                 if (p->fbo_refraction == 0)
6275                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6276                         }
6277                 }
6278                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6279                 {
6280                         if (!p->texture_camera)
6281                                 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);
6282                         if (!p->texture_camera)
6283                                 goto error;
6284                         if (usewaterfbo)
6285                         {
6286                                 if (r_fb.water.depthtexture == NULL)
6287                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6288                                 if (p->fbo_camera == 0)
6289                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6290                         }
6291                 }
6292
6293                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6294                 {
6295                         if (!p->texture_reflection)
6296                                 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);
6297                         if (!p->texture_reflection)
6298                                 goto error;
6299                         if (usewaterfbo)
6300                         {
6301                                 if (r_fb.water.depthtexture == NULL)
6302                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6303                                 if (p->fbo_reflection == 0)
6304                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6305                         }
6306                 }
6307         }
6308
6309         // render views
6310         r_refdef.view = originalview;
6311         r_refdef.view.showdebug = false;
6312         r_refdef.view.width = r_fb.water.waterwidth;
6313         r_refdef.view.height = r_fb.water.waterheight;
6314         r_refdef.view.useclipplane = true;
6315         myview = r_refdef.view;
6316         r_fb.water.renderingscene = true;
6317         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6318         {
6319                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6320                         continue;
6321                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6322                 {
6323                         r_refdef.view = myview;
6324                         if(r_water_scissormode.integer)
6325                         {
6326                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6327                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6328                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6329                         }
6330
6331                         // render reflected scene and copy into texture
6332                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6333                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6334                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6335                         r_refdef.view.clipplane = p->plane;
6336                         // reverse the cullface settings for this render
6337                         r_refdef.view.cullface_front = GL_FRONT;
6338                         r_refdef.view.cullface_back = GL_BACK;
6339                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6340                         {
6341                                 r_refdef.view.usecustompvs = true;
6342                                 if (p->pvsvalid)
6343                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6344                                 else
6345                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6346                         }
6347
6348                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6349                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6350                         R_ClearScreen(r_refdef.fogenabled);
6351                         if(r_water_scissormode.integer & 2)
6352                                 R_View_UpdateWithScissor(myscissor);
6353                         else
6354                                 R_View_Update();
6355                         R_AnimCache_CacheVisibleEntities();
6356                         if(r_water_scissormode.integer & 1)
6357                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6358                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6359
6360                         if (!p->fbo_reflection)
6361                                 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);
6362                         r_fb.water.hideplayer = false;
6363                 }
6364
6365                 // render the normal view scene and copy into texture
6366                 // (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)
6367                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6368                 {
6369                         r_refdef.view = myview;
6370                         if(r_water_scissormode.integer)
6371                         {
6372                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6373                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6374                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6375                         }
6376
6377                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6378
6379                         r_refdef.view.clipplane = p->plane;
6380                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6381                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6382
6383                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6384                         {
6385                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6386                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6387                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6388                                 R_RenderView_UpdateViewVectors();
6389                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6390                                 {
6391                                         r_refdef.view.usecustompvs = true;
6392                                         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);
6393                                 }
6394                         }
6395
6396                         PlaneClassify(&r_refdef.view.clipplane);
6397
6398                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6399                         R_ClearScreen(r_refdef.fogenabled);
6400                         if(r_water_scissormode.integer & 2)
6401                                 R_View_UpdateWithScissor(myscissor);
6402                         else
6403                                 R_View_Update();
6404                         R_AnimCache_CacheVisibleEntities();
6405                         if(r_water_scissormode.integer & 1)
6406                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6407                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6408
6409                         if (!p->fbo_refraction)
6410                                 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);
6411                         r_fb.water.hideplayer = false;
6412                 }
6413                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6414                 {
6415                         r_refdef.view = myview;
6416
6417                         r_refdef.view.clipplane = p->plane;
6418                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6419                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6420
6421                         r_refdef.view.width = r_fb.water.camerawidth;
6422                         r_refdef.view.height = r_fb.water.cameraheight;
6423                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6424                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6425                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6426                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6427
6428                         if(p->camera_entity)
6429                         {
6430                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6431                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6432                         }
6433
6434                         // note: all of the view is used for displaying... so
6435                         // there is no use in scissoring
6436
6437                         // reverse the cullface settings for this render
6438                         r_refdef.view.cullface_front = GL_FRONT;
6439                         r_refdef.view.cullface_back = GL_BACK;
6440                         // also reverse the view matrix
6441                         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
6442                         R_RenderView_UpdateViewVectors();
6443                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6444                         {
6445                                 r_refdef.view.usecustompvs = true;
6446                                 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);
6447                         }
6448                         
6449                         // camera needs no clipplane
6450                         r_refdef.view.useclipplane = false;
6451
6452                         PlaneClassify(&r_refdef.view.clipplane);
6453
6454                         r_fb.water.hideplayer = false;
6455
6456                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6457                         R_ClearScreen(r_refdef.fogenabled);
6458                         R_View_Update();
6459                         R_AnimCache_CacheVisibleEntities();
6460                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6461
6462                         if (!p->fbo_camera)
6463                                 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);
6464                         r_fb.water.hideplayer = false;
6465                 }
6466
6467         }
6468         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6469         r_fb.water.renderingscene = false;
6470         r_refdef.view = originalview;
6471         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6472         if (!r_fb.water.depthtexture)
6473                 R_ClearScreen(r_refdef.fogenabled);
6474         R_View_Update();
6475         R_AnimCache_CacheVisibleEntities();
6476         goto finish;
6477 error:
6478         r_refdef.view = originalview;
6479         r_fb.water.renderingscene = false;
6480         Cvar_SetValueQuick(&r_water, 0);
6481         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6482 finish:
6483         // lowquality hack, restore cvars
6484         if (qualityreduction > 0)
6485         {
6486                 if (qualityreduction >= 1)
6487                 {
6488                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6489                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6490                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6491                 }
6492                 if (qualityreduction >= 2)
6493                 {
6494                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6495                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6496                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6497                 }
6498         }
6499 }
6500
6501 static void R_Bloom_StartFrame(void)
6502 {
6503         int i;
6504         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6505         int viewwidth, viewheight;
6506         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6507         textype_t textype = TEXTYPE_COLORBUFFER;
6508
6509         switch (vid.renderpath)
6510         {
6511         case RENDERPATH_GL20:
6512                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6513                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6514                 {
6515                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6516                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6517                 }
6518                 break;
6519         case RENDERPATH_GL11:
6520         case RENDERPATH_GL13:
6521         case RENDERPATH_GLES1:
6522         case RENDERPATH_GLES2:
6523         case RENDERPATH_D3D9:
6524         case RENDERPATH_D3D10:
6525         case RENDERPATH_D3D11:
6526                 r_fb.usedepthtextures = false;
6527                 break;
6528         case RENDERPATH_SOFT:
6529                 r_fb.usedepthtextures = true;
6530                 break;
6531         }
6532
6533         if (r_viewscale_fpsscaling.integer)
6534         {
6535                 double actualframetime;
6536                 double targetframetime;
6537                 double adjust;
6538                 actualframetime = r_refdef.lastdrawscreentime;
6539                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6540                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6541                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6542                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6543                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6544                 viewscalefpsadjusted += adjust;
6545                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6546         }
6547         else
6548                 viewscalefpsadjusted = 1.0f;
6549
6550         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6551
6552         switch(vid.renderpath)
6553         {
6554         case RENDERPATH_GL20:
6555         case RENDERPATH_D3D9:
6556         case RENDERPATH_D3D10:
6557         case RENDERPATH_D3D11:
6558         case RENDERPATH_SOFT:
6559         case RENDERPATH_GLES2:
6560                 break;
6561         case RENDERPATH_GL11:
6562         case RENDERPATH_GL13:
6563         case RENDERPATH_GLES1:
6564                 return;
6565         }
6566
6567         // set bloomwidth and bloomheight to the bloom resolution that will be
6568         // used (often less than the screen resolution for faster rendering)
6569         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6570         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6571         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6572         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6573         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6574
6575         // calculate desired texture sizes
6576         if (vid.support.arb_texture_non_power_of_two)
6577         {
6578                 screentexturewidth = vid.width;
6579                 screentextureheight = vid.height;
6580                 bloomtexturewidth = r_fb.bloomwidth;
6581                 bloomtextureheight = r_fb.bloomheight;
6582         }
6583         else
6584         {
6585                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6586                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6587                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6588                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6589         }
6590
6591         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))
6592         {
6593                 Cvar_SetValueQuick(&r_bloom, 0);
6594                 Cvar_SetValueQuick(&r_motionblur, 0);
6595                 Cvar_SetValueQuick(&r_damageblur, 0);
6596         }
6597
6598         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6599          && !r_bloom.integer
6600          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6601          && !useviewfbo
6602          && r_viewscale.value == 1.0f
6603          && !r_viewscale_fpsscaling.integer)
6604                 screentexturewidth = screentextureheight = 0;
6605         if (!r_bloom.integer)
6606                 bloomtexturewidth = bloomtextureheight = 0;
6607
6608         // allocate textures as needed
6609         if (r_fb.screentexturewidth != screentexturewidth
6610          || r_fb.screentextureheight != screentextureheight
6611          || r_fb.bloomtexturewidth != bloomtexturewidth
6612          || r_fb.bloomtextureheight != bloomtextureheight
6613          || r_fb.textype != textype
6614          || useviewfbo != (r_fb.fbo != 0))
6615         {
6616                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6617                 {
6618                         if (r_fb.bloomtexture[i])
6619                                 R_FreeTexture(r_fb.bloomtexture[i]);
6620                         r_fb.bloomtexture[i] = NULL;
6621
6622                         if (r_fb.bloomfbo[i])
6623                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6624                         r_fb.bloomfbo[i] = 0;
6625                 }
6626
6627                 if (r_fb.fbo)
6628                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6629                 r_fb.fbo = 0;
6630
6631                 if (r_fb.colortexture)
6632                         R_FreeTexture(r_fb.colortexture);
6633                 r_fb.colortexture = NULL;
6634
6635                 if (r_fb.depthtexture)
6636                         R_FreeTexture(r_fb.depthtexture);
6637                 r_fb.depthtexture = NULL;
6638
6639                 if (r_fb.ghosttexture)
6640                         R_FreeTexture(r_fb.ghosttexture);
6641                 r_fb.ghosttexture = NULL;
6642
6643                 r_fb.screentexturewidth = screentexturewidth;
6644                 r_fb.screentextureheight = screentextureheight;
6645                 r_fb.bloomtexturewidth = bloomtexturewidth;
6646                 r_fb.bloomtextureheight = bloomtextureheight;
6647                 r_fb.textype = textype;
6648
6649                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6650                 {
6651                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6652                                 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);
6653                         r_fb.ghosttexture_valid = false;
6654                         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);
6655                         if (useviewfbo)
6656                         {
6657                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6658                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6659                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6660                         }
6661                 }
6662
6663                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6664                 {
6665                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6666                         {
6667                                 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);
6668                                 if (useviewfbo)
6669                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6670                         }
6671                 }
6672         }
6673
6674         // bloom texture is a different resolution
6675         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6676         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6677         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6678         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6679         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6680
6681         // set up a texcoord array for the full resolution screen image
6682         // (we have to keep this around to copy back during final render)
6683         r_fb.screentexcoord2f[0] = 0;
6684         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6685         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6686         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6687         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6688         r_fb.screentexcoord2f[5] = 0;
6689         r_fb.screentexcoord2f[6] = 0;
6690         r_fb.screentexcoord2f[7] = 0;
6691
6692         if(r_fb.fbo) 
6693         {
6694                 for (i = 1;i < 8;i += 2)
6695                 {
6696                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6697                 }
6698         }
6699
6700         // set up a texcoord array for the reduced resolution bloom image
6701         // (which will be additive blended over the screen image)
6702         r_fb.bloomtexcoord2f[0] = 0;
6703         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6704         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6705         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6706         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6707         r_fb.bloomtexcoord2f[5] = 0;
6708         r_fb.bloomtexcoord2f[6] = 0;
6709         r_fb.bloomtexcoord2f[7] = 0;
6710
6711         switch(vid.renderpath)
6712         {
6713         case RENDERPATH_GL11:
6714         case RENDERPATH_GL13:
6715         case RENDERPATH_GL20:
6716         case RENDERPATH_SOFT:
6717         case RENDERPATH_GLES1:
6718         case RENDERPATH_GLES2:
6719                 break;
6720         case RENDERPATH_D3D9:
6721         case RENDERPATH_D3D10:
6722         case RENDERPATH_D3D11:
6723                 for (i = 0;i < 4;i++)
6724                 {
6725                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6726                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6727                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6728                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6729                 }
6730                 break;
6731         }
6732
6733         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6734
6735         if (r_fb.fbo)
6736                 r_refdef.view.clear = true;
6737 }
6738
6739 static void R_Bloom_MakeTexture(void)
6740 {
6741         int x, range, dir;
6742         float xoffset, yoffset, r, brighten;
6743         rtexture_t *intex;
6744         float colorscale = r_bloom_colorscale.value;
6745
6746         r_refdef.stats[r_stat_bloom]++;
6747     
6748 #if 0
6749     // this copy is unnecessary since it happens in R_BlendView already
6750         if (!r_fb.fbo)
6751         {
6752                 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);
6753                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6754         }
6755 #endif
6756
6757         // scale down screen texture to the bloom texture size
6758         CHECKGLERROR
6759         r_fb.bloomindex = 0;
6760         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6761         R_SetViewport(&r_fb.bloomviewport);
6762         GL_CullFace(GL_NONE);
6763         GL_DepthTest(false);
6764         GL_BlendFunc(GL_ONE, GL_ZERO);
6765         GL_Color(colorscale, colorscale, colorscale, 1);
6766         // 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...
6767         switch(vid.renderpath)
6768         {
6769         case RENDERPATH_GL11:
6770         case RENDERPATH_GL13:
6771         case RENDERPATH_GL20:
6772         case RENDERPATH_GLES1:
6773         case RENDERPATH_GLES2:
6774         case RENDERPATH_SOFT:
6775                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6776                 break;
6777         case RENDERPATH_D3D9:
6778         case RENDERPATH_D3D10:
6779         case RENDERPATH_D3D11:
6780                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6781                 break;
6782         }
6783         // TODO: do boxfilter scale-down in shader?
6784         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6785         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6786         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6787
6788         // we now have a properly scaled bloom image
6789         if (!r_fb.bloomfbo[r_fb.bloomindex])
6790         {
6791                 // copy it into the bloom texture
6792                 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);
6793                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6794         }
6795
6796         // multiply bloom image by itself as many times as desired
6797         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6798         {
6799                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6800                 r_fb.bloomindex ^= 1;
6801                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6802                 x *= 2;
6803                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6804                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6805                 {
6806                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6807                         GL_Color(r,r,r,1); // apply fix factor
6808                 }
6809                 else
6810                 {
6811                         if(x <= 2)
6812                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6813                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6814                         GL_Color(1,1,1,1); // no fix factor supported here
6815                 }
6816                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6817                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6818                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6819                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6820
6821                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6822                 {
6823                         // copy the darkened image to a texture
6824                         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);
6825                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6826                 }
6827         }
6828
6829         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6830         brighten = r_bloom_brighten.value;
6831         brighten = sqrt(brighten);
6832         if(range >= 1)
6833                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6834
6835         for (dir = 0;dir < 2;dir++)
6836         {
6837                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6838                 r_fb.bloomindex ^= 1;
6839                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6840                 // blend on at multiple vertical offsets to achieve a vertical blur
6841                 // TODO: do offset blends using GLSL
6842                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6843                 GL_BlendFunc(GL_ONE, GL_ZERO);
6844                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6845                 for (x = -range;x <= range;x++)
6846                 {
6847                         if (!dir){xoffset = 0;yoffset = x;}
6848                         else {xoffset = x;yoffset = 0;}
6849                         xoffset /= (float)r_fb.bloomtexturewidth;
6850                         yoffset /= (float)r_fb.bloomtextureheight;
6851                         // compute a texcoord array with the specified x and y offset
6852                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6853                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6854                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6855                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6856                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6857                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6858                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6859                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6860                         // this r value looks like a 'dot' particle, fading sharply to
6861                         // black at the edges
6862                         // (probably not realistic but looks good enough)
6863                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6864                         //r = brighten/(range*2+1);
6865                         r = brighten / (range * 2 + 1);
6866                         if(range >= 1)
6867                                 r *= (1 - x*x/(float)(range*range));
6868                         GL_Color(r, r, r, 1);
6869                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6870                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6871                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6872                         GL_BlendFunc(GL_ONE, GL_ONE);
6873                 }
6874
6875                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6876                 {
6877                         // copy the vertically or horizontally blurred bloom view to a texture
6878                         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);
6879                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6880                 }
6881         }
6882 }
6883
6884 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6885 {
6886         dpuint64 permutation;
6887         float uservecs[4][4];
6888
6889         R_EntityMatrix(&identitymatrix);
6890
6891         switch (vid.renderpath)
6892         {
6893         case RENDERPATH_GL20:
6894         case RENDERPATH_D3D9:
6895         case RENDERPATH_D3D10:
6896         case RENDERPATH_D3D11:
6897         case RENDERPATH_SOFT:
6898         case RENDERPATH_GLES2:
6899                 permutation =
6900                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6901                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6902                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6903                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6904                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6905
6906                 if (r_fb.colortexture)
6907                 {
6908                         if (!r_fb.fbo)
6909                         {
6910                                 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);
6911                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6912                         }
6913
6914                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6915                         {
6916                                 // declare variables
6917                                 float blur_factor, blur_mouseaccel, blur_velocity;
6918                                 static float blur_average; 
6919                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6920
6921                                 // set a goal for the factoring
6922                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6923                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6924                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6925                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6926                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6927                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6928
6929                                 // from the goal, pick an averaged value between goal and last value
6930                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6931                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6932
6933                                 // enforce minimum amount of blur 
6934                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6935
6936                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6937
6938                                 // calculate values into a standard alpha
6939                                 cl.motionbluralpha = 1 - exp(-
6940                                                 (
6941                                                  (r_motionblur.value * blur_factor / 80)
6942                                                  +
6943                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6944                                                 )
6945                                                 /
6946                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6947                                           );
6948
6949                                 // randomization for the blur value to combat persistent ghosting
6950                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6951                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6952
6953                                 // apply the blur
6954                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6955                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6956                                 {
6957                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6958                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6959                                         switch(vid.renderpath)
6960                                         {
6961                                         case RENDERPATH_GL11:
6962                                         case RENDERPATH_GL13:
6963                                         case RENDERPATH_GL20:
6964                                         case RENDERPATH_GLES1:
6965                                         case RENDERPATH_GLES2:
6966                                         case RENDERPATH_SOFT:
6967                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6968                                                 break;
6969                                         case RENDERPATH_D3D9:
6970                                         case RENDERPATH_D3D10:
6971                                         case RENDERPATH_D3D11:
6972                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6973                                                 break;
6974                                         }
6975                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6976                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6977                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6978                                 }
6979
6980                                 // updates old view angles for next pass
6981                                 VectorCopy(cl.viewangles, blur_oldangles);
6982
6983                                 // copy view into the ghost texture
6984                                 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);
6985                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6986                                 r_fb.ghosttexture_valid = true;
6987                         }
6988                 }
6989                 else
6990                 {
6991                         // no r_fb.colortexture means we're rendering to the real fb
6992                         // we may still have to do view tint...
6993                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6994                         {
6995                                 // apply a color tint to the whole view
6996                                 R_ResetViewRendering2D(0, NULL, NULL);
6997                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6998                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6999                                 R_SetupShader_Generic_NoTexture(false, true);
7000                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7001                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7002                         }
7003                         break; // no screen processing, no bloom, skip it
7004                 }
7005
7006                 if (r_fb.bloomtexture[0])
7007                 {
7008                         // make the bloom texture
7009                         R_Bloom_MakeTexture();
7010                 }
7011
7012 #if _MSC_VER >= 1400
7013 #define sscanf sscanf_s
7014 #endif
7015                 memset(uservecs, 0, sizeof(uservecs));
7016                 if (r_glsl_postprocess_uservec1_enable.integer)
7017                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7018                 if (r_glsl_postprocess_uservec2_enable.integer)
7019                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7020                 if (r_glsl_postprocess_uservec3_enable.integer)
7021                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7022                 if (r_glsl_postprocess_uservec4_enable.integer)
7023                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7024
7025                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
7026                 GL_Color(1, 1, 1, 1);
7027                 GL_BlendFunc(GL_ONE, GL_ZERO);
7028
7029                 switch(vid.renderpath)
7030                 {
7031                 case RENDERPATH_GL20:
7032                 case RENDERPATH_GLES2:
7033                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7034                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7035                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
7036                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
7037                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
7038                         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]);
7039                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7040                         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]);
7041                         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]);
7042                         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]);
7043                         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]);
7044                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7045                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7046                         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);
7047                         break;
7048                 case RENDERPATH_D3D9:
7049 #ifdef SUPPORTD3D
7050                         // 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...
7051                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7052                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
7053                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7054                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7055                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7056                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7057                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7058                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7059                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7060                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7061                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7062                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
7063                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7064                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7065 #endif
7066                         break;
7067                 case RENDERPATH_D3D10:
7068                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7069                         break;
7070                 case RENDERPATH_D3D11:
7071                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7072                         break;
7073                 case RENDERPATH_SOFT:
7074                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7075                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7076                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7077                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7078                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7079                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7080                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7081                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7082                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7083                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7084                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7085                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7086                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7087                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7088                         break;
7089                 default:
7090                         break;
7091                 }
7092                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7093                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7094                 break;
7095         case RENDERPATH_GL11:
7096         case RENDERPATH_GL13:
7097         case RENDERPATH_GLES1:
7098                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7099                 {
7100                         // apply a color tint to the whole view
7101                         R_ResetViewRendering2D(0, NULL, NULL);
7102                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7103                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7104                         R_SetupShader_Generic_NoTexture(false, true);
7105                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7106                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7107                 }
7108                 break;
7109         }
7110 }
7111
7112 matrix4x4_t r_waterscrollmatrix;
7113
7114 void R_UpdateFog(void)
7115 {
7116         // Nehahra fog
7117         if (gamemode == GAME_NEHAHRA)
7118         {
7119                 if (gl_fogenable.integer)
7120                 {
7121                         r_refdef.oldgl_fogenable = true;
7122                         r_refdef.fog_density = gl_fogdensity.value;
7123                         r_refdef.fog_red = gl_fogred.value;
7124                         r_refdef.fog_green = gl_foggreen.value;
7125                         r_refdef.fog_blue = gl_fogblue.value;
7126                         r_refdef.fog_alpha = 1;
7127                         r_refdef.fog_start = 0;
7128                         r_refdef.fog_end = gl_skyclip.value;
7129                         r_refdef.fog_height = 1<<30;
7130                         r_refdef.fog_fadedepth = 128;
7131                 }
7132                 else if (r_refdef.oldgl_fogenable)
7133                 {
7134                         r_refdef.oldgl_fogenable = false;
7135                         r_refdef.fog_density = 0;
7136                         r_refdef.fog_red = 0;
7137                         r_refdef.fog_green = 0;
7138                         r_refdef.fog_blue = 0;
7139                         r_refdef.fog_alpha = 0;
7140                         r_refdef.fog_start = 0;
7141                         r_refdef.fog_end = 0;
7142                         r_refdef.fog_height = 1<<30;
7143                         r_refdef.fog_fadedepth = 128;
7144                 }
7145         }
7146
7147         // fog parms
7148         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7149         r_refdef.fog_start = max(0, r_refdef.fog_start);
7150         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7151
7152         if (r_refdef.fog_density && r_drawfog.integer)
7153         {
7154                 r_refdef.fogenabled = true;
7155                 // this is the point where the fog reaches 0.9986 alpha, which we
7156                 // consider a good enough cutoff point for the texture
7157                 // (0.9986 * 256 == 255.6)
7158                 if (r_fog_exp2.integer)
7159                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7160                 else
7161                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7162                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7163                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7164                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7165                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7166                         R_BuildFogHeightTexture();
7167                 // fog color was already set
7168                 // update the fog texture
7169                 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)
7170                         R_BuildFogTexture();
7171                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7172                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7173         }
7174         else
7175                 r_refdef.fogenabled = false;
7176
7177         // fog color
7178         if (r_refdef.fog_density)
7179         {
7180                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7181                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7182                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7183
7184                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7185                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7186                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7187                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7188
7189                 {
7190                         vec3_t fogvec;
7191                         VectorCopy(r_refdef.fogcolor, fogvec);
7192                         //   color.rgb *= ContrastBoost * SceneBrightness;
7193                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7194                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7195                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7196                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7197                 }
7198         }
7199 }
7200
7201 void R_UpdateVariables(void)
7202 {
7203         R_Textures_Frame();
7204
7205         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7206
7207         r_refdef.farclip = r_farclip_base.value;
7208         if (r_refdef.scene.worldmodel)
7209                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7210         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7211
7212         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7213                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7214         r_refdef.polygonfactor = 0;
7215         r_refdef.polygonoffset = 0;
7216         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7217         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7218
7219         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7220         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7221         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7222         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7223         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7224         if (FAKELIGHT_ENABLED)
7225         {
7226                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7227         }
7228         else if (r_refdef.scene.worldmodel)
7229         {
7230                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7231         }
7232         if (r_showsurfaces.integer)
7233         {
7234                 r_refdef.scene.rtworld = false;
7235                 r_refdef.scene.rtworldshadows = false;
7236                 r_refdef.scene.rtdlight = false;
7237                 r_refdef.scene.rtdlightshadows = false;
7238                 r_refdef.lightmapintensity = 0;
7239         }
7240
7241         r_gpuskeletal = false;
7242         switch(vid.renderpath)
7243         {
7244         case RENDERPATH_GL20:
7245                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7246         case RENDERPATH_D3D9:
7247         case RENDERPATH_D3D10:
7248         case RENDERPATH_D3D11:
7249         case RENDERPATH_SOFT:
7250         case RENDERPATH_GLES2:
7251                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7252                 {
7253                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7254                         {
7255                                 // build GLSL gamma texture
7256 #define RAMPWIDTH 256
7257                                 unsigned short ramp[RAMPWIDTH * 3];
7258                                 unsigned char rampbgr[RAMPWIDTH][4];
7259                                 int i;
7260
7261                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7262
7263                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7264                                 for(i = 0; i < RAMPWIDTH; ++i)
7265                                 {
7266                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7267                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7268                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7269                                         rampbgr[i][3] = 0;
7270                                 }
7271                                 if (r_texture_gammaramps)
7272                                 {
7273                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7274                                 }
7275                                 else
7276                                 {
7277                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7278                                 }
7279                         }
7280                 }
7281                 else
7282                 {
7283                         // remove GLSL gamma texture
7284                 }
7285                 break;
7286         case RENDERPATH_GL11:
7287         case RENDERPATH_GL13:
7288         case RENDERPATH_GLES1:
7289                 break;
7290         }
7291 }
7292
7293 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7294 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7295 /*
7296 ================
7297 R_SelectScene
7298 ================
7299 */
7300 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7301         if( scenetype != r_currentscenetype ) {
7302                 // store the old scenetype
7303                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7304                 r_currentscenetype = scenetype;
7305                 // move in the new scene
7306                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7307         }
7308 }
7309
7310 /*
7311 ================
7312 R_GetScenePointer
7313 ================
7314 */
7315 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7316 {
7317         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7318         if( scenetype == r_currentscenetype ) {
7319                 return &r_refdef.scene;
7320         } else {
7321                 return &r_scenes_store[ scenetype ];
7322         }
7323 }
7324
7325 static int R_SortEntities_Compare(const void *ap, const void *bp)
7326 {
7327         const entity_render_t *a = *(const entity_render_t **)ap;
7328         const entity_render_t *b = *(const entity_render_t **)bp;
7329
7330         // 1. compare model
7331         if(a->model < b->model)
7332                 return -1;
7333         if(a->model > b->model)
7334                 return +1;
7335
7336         // 2. compare skin
7337         // TODO possibly calculate the REAL skinnum here first using
7338         // skinscenes?
7339         if(a->skinnum < b->skinnum)
7340                 return -1;
7341         if(a->skinnum > b->skinnum)
7342                 return +1;
7343
7344         // everything we compared is equal
7345         return 0;
7346 }
7347 static void R_SortEntities(void)
7348 {
7349         // below or equal 2 ents, sorting never gains anything
7350         if(r_refdef.scene.numentities <= 2)
7351                 return;
7352         // sort
7353         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7354 }
7355
7356 /*
7357 ================
7358 R_RenderView
7359 ================
7360 */
7361 int dpsoftrast_test;
7362 extern cvar_t r_shadow_bouncegrid;
7363 void R_RenderView(void)
7364 {
7365         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7366         int fbo;
7367         rtexture_t *depthtexture;
7368         rtexture_t *colortexture;
7369
7370         dpsoftrast_test = r_test.integer;
7371
7372         if (r_timereport_active)
7373                 R_TimeReport("start");
7374         r_textureframe++; // used only by R_GetCurrentTexture
7375         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7376
7377         if(R_CompileShader_CheckStaticParms())
7378                 R_GLSL_Restart_f();
7379
7380         if (!r_drawentities.integer)
7381                 r_refdef.scene.numentities = 0;
7382         else if (r_sortentities.integer)
7383                 R_SortEntities();
7384
7385         R_AnimCache_ClearCache();
7386
7387         /* adjust for stereo display */
7388         if(R_Stereo_Active())
7389         {
7390                 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);
7391                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7392         }
7393
7394         if (r_refdef.view.isoverlay)
7395         {
7396                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7397                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7398                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7399                 R_TimeReport("depthclear");
7400
7401                 r_refdef.view.showdebug = false;
7402
7403                 r_fb.water.enabled = false;
7404                 r_fb.water.numwaterplanes = 0;
7405
7406                 R_RenderScene(0, NULL, NULL);
7407
7408                 r_refdef.view.matrix = originalmatrix;
7409
7410                 CHECKGLERROR
7411                 return;
7412         }
7413
7414         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7415         {
7416                 r_refdef.view.matrix = originalmatrix;
7417                 return;
7418         }
7419
7420         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7421
7422         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7423                 // in sRGB fallback, behave similar to true sRGB: convert this
7424                 // value from linear to sRGB
7425                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7426
7427         R_RenderView_UpdateViewVectors();
7428
7429         R_Shadow_UpdateWorldLightSelection();
7430
7431         R_Bloom_StartFrame();
7432
7433         // apply bloom brightness offset
7434         if(r_fb.bloomtexture[0])
7435                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7436
7437         R_Water_StartFrame();
7438
7439         // now we probably have an fbo to render into
7440         fbo = r_fb.fbo;
7441         depthtexture = r_fb.depthtexture;
7442         colortexture = r_fb.colortexture;
7443
7444         CHECKGLERROR
7445         if (r_timereport_active)
7446                 R_TimeReport("viewsetup");
7447
7448         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7449
7450         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7451         {
7452                 R_ClearScreen(r_refdef.fogenabled);
7453                 if (r_timereport_active)
7454                         R_TimeReport("viewclear");
7455         }
7456         r_refdef.view.clear = true;
7457
7458         r_refdef.view.showdebug = true;
7459
7460         R_View_Update();
7461         if (r_timereport_active)
7462                 R_TimeReport("visibility");
7463
7464         R_AnimCache_CacheVisibleEntities();
7465         if (r_timereport_active)
7466                 R_TimeReport("animcache");
7467
7468         R_Shadow_UpdateBounceGridTexture();
7469         if (r_timereport_active && r_shadow_bouncegrid.integer)
7470                 R_TimeReport("bouncegrid");
7471
7472         r_fb.water.numwaterplanes = 0;
7473         if (r_fb.water.enabled)
7474                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7475
7476         R_RenderScene(fbo, depthtexture, colortexture);
7477         r_fb.water.numwaterplanes = 0;
7478
7479         R_BlendView(fbo, depthtexture, colortexture);
7480         if (r_timereport_active)
7481                 R_TimeReport("blendview");
7482
7483         GL_Scissor(0, 0, vid.width, vid.height);
7484         GL_ScissorTest(false);
7485
7486         r_refdef.view.matrix = originalmatrix;
7487
7488         CHECKGLERROR
7489 }
7490
7491 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7492 {
7493         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7494         {
7495                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7496                 if (r_timereport_active)
7497                         R_TimeReport("waterworld");
7498         }
7499
7500         // don't let sound skip if going slow
7501         if (r_refdef.scene.extraupdate)
7502                 S_ExtraUpdate ();
7503
7504         R_DrawModelsAddWaterPlanes();
7505         if (r_timereport_active)
7506                 R_TimeReport("watermodels");
7507
7508         if (r_fb.water.numwaterplanes)
7509         {
7510                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7511                 if (r_timereport_active)
7512                         R_TimeReport("waterscenes");
7513         }
7514 }
7515
7516 extern cvar_t cl_locs_show;
7517 static void R_DrawLocs(void);
7518 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7519 static void R_DrawModelDecals(void);
7520 extern cvar_t cl_decals_newsystem;
7521 extern qboolean r_shadow_usingdeferredprepass;
7522 extern int r_shadow_shadowmapatlas_modelshadows_size;
7523 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7524 {
7525         qboolean shadowmapping = false;
7526
7527         if (r_timereport_active)
7528                 R_TimeReport("beginscene");
7529
7530         r_refdef.stats[r_stat_renders]++;
7531
7532         R_UpdateFog();
7533
7534         // don't let sound skip if going slow
7535         if (r_refdef.scene.extraupdate)
7536                 S_ExtraUpdate ();
7537
7538         R_MeshQueue_BeginScene();
7539
7540         R_SkyStartFrame();
7541
7542         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);
7543
7544         if (r_timereport_active)
7545                 R_TimeReport("skystartframe");
7546
7547         if (cl.csqc_vidvars.drawworld)
7548         {
7549                 // don't let sound skip if going slow
7550                 if (r_refdef.scene.extraupdate)
7551                         S_ExtraUpdate ();
7552
7553                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7554                 {
7555                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7556                         if (r_timereport_active)
7557                                 R_TimeReport("worldsky");
7558                 }
7559
7560                 if (R_DrawBrushModelsSky() && r_timereport_active)
7561                         R_TimeReport("bmodelsky");
7562
7563                 if (skyrendermasked && skyrenderlater)
7564                 {
7565                         // we have to force off the water clipping plane while rendering sky
7566                         R_SetupView(false, fbo, depthtexture, colortexture);
7567                         R_Sky();
7568                         R_SetupView(true, fbo, depthtexture, colortexture);
7569                         if (r_timereport_active)
7570                                 R_TimeReport("sky");
7571                 }
7572         }
7573
7574         R_Shadow_PrepareModelShadows();
7575         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7576         if (r_timereport_active)
7577                 R_TimeReport("preparelights");
7578
7579         // render all the shadowmaps that will be used for this view
7580         shadowmapping = R_Shadow_ShadowMappingEnabled();
7581         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7582         {
7583                 R_Shadow_DrawShadowMaps();
7584                 if (r_timereport_active)
7585                         R_TimeReport("shadowmaps");
7586         }
7587
7588         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7589         if (r_shadow_usingdeferredprepass)
7590                 R_Shadow_DrawPrepass();
7591
7592         // now we begin the forward pass of the view render
7593         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7594         {
7595                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7596                 if (r_timereport_active)
7597                         R_TimeReport("worlddepth");
7598         }
7599         if (r_depthfirst.integer >= 2)
7600         {
7601                 R_DrawModelsDepth();
7602                 if (r_timereport_active)
7603                         R_TimeReport("modeldepth");
7604         }
7605
7606         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7607         {
7608                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7609                 if (r_timereport_active)
7610                         R_TimeReport("world");
7611         }
7612
7613         // don't let sound skip if going slow
7614         if (r_refdef.scene.extraupdate)
7615                 S_ExtraUpdate ();
7616
7617         R_DrawModels();
7618         if (r_timereport_active)
7619                 R_TimeReport("models");
7620
7621         // don't let sound skip if going slow
7622         if (r_refdef.scene.extraupdate)
7623                 S_ExtraUpdate ();
7624
7625         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7626         {
7627                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7628                 R_Shadow_DrawModelShadows();
7629                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7630                 // don't let sound skip if going slow
7631                 if (r_refdef.scene.extraupdate)
7632                         S_ExtraUpdate ();
7633         }
7634
7635         if (!r_shadow_usingdeferredprepass)
7636         {
7637                 R_Shadow_DrawLights();
7638                 if (r_timereport_active)
7639                         R_TimeReport("rtlights");
7640         }
7641
7642         // don't let sound skip if going slow
7643         if (r_refdef.scene.extraupdate)
7644                 S_ExtraUpdate ();
7645
7646         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7647         {
7648                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7649                 R_Shadow_DrawModelShadows();
7650                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7651                 // don't let sound skip if going slow
7652                 if (r_refdef.scene.extraupdate)
7653                         S_ExtraUpdate ();
7654         }
7655
7656         if (cl.csqc_vidvars.drawworld)
7657         {
7658                 if (cl_decals_newsystem.integer)
7659                 {
7660                         R_DrawModelDecals();
7661                         if (r_timereport_active)
7662                                 R_TimeReport("modeldecals");
7663                 }
7664                 else
7665                 {
7666                         R_DrawDecals();
7667                         if (r_timereport_active)
7668                                 R_TimeReport("decals");
7669                 }
7670
7671                 R_DrawParticles();
7672                 if (r_timereport_active)
7673                         R_TimeReport("particles");
7674
7675                 R_DrawExplosions();
7676                 if (r_timereport_active)
7677                         R_TimeReport("explosions");
7678         }
7679
7680         if (cl.csqc_loaded)
7681                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7682
7683         if (r_refdef.view.showdebug)
7684         {
7685                 if (cl_locs_show.integer)
7686                 {
7687                         R_DrawLocs();
7688                         if (r_timereport_active)
7689                                 R_TimeReport("showlocs");
7690                 }
7691
7692                 if (r_drawportals.integer)
7693                 {
7694                         R_DrawPortals();
7695                         if (r_timereport_active)
7696                                 R_TimeReport("portals");
7697                 }
7698
7699                 if (r_showbboxes_client.value > 0)
7700                 {
7701                         R_DrawEntityBBoxes(CLVM_prog);
7702                         if (r_timereport_active)
7703                                 R_TimeReport("clbboxes");
7704                 }
7705                 if (r_showbboxes.value > 0)
7706                 {
7707                         R_DrawEntityBBoxes(SVVM_prog);
7708                         if (r_timereport_active)
7709                                 R_TimeReport("svbboxes");
7710                 }
7711         }
7712
7713         if (r_transparent.integer)
7714         {
7715                 R_MeshQueue_RenderTransparent();
7716                 if (r_timereport_active)
7717                         R_TimeReport("drawtrans");
7718         }
7719
7720         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))
7721         {
7722                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7723                 if (r_timereport_active)
7724                         R_TimeReport("worlddebug");
7725                 R_DrawModelsDebug();
7726                 if (r_timereport_active)
7727                         R_TimeReport("modeldebug");
7728         }
7729
7730         if (cl.csqc_vidvars.drawworld)
7731         {
7732                 R_Shadow_DrawCoronas();
7733                 if (r_timereport_active)
7734                         R_TimeReport("coronas");
7735         }
7736
7737 #if 0
7738         {
7739                 GL_DepthTest(false);
7740                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7741                 GL_Color(1, 1, 1, 1);
7742                 qglBegin(GL_POLYGON);
7743                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7744                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7745                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7746                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7747                 qglEnd();
7748                 qglBegin(GL_POLYGON);
7749                 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]);
7750                 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]);
7751                 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]);
7752                 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]);
7753                 qglEnd();
7754                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7755         }
7756 #endif
7757
7758         // don't let sound skip if going slow
7759         if (r_refdef.scene.extraupdate)
7760                 S_ExtraUpdate ();
7761 }
7762
7763 static const unsigned short bboxelements[36] =
7764 {
7765         5, 1, 3, 5, 3, 7,
7766         6, 2, 0, 6, 0, 4,
7767         7, 3, 2, 7, 2, 6,
7768         4, 0, 1, 4, 1, 5,
7769         4, 5, 7, 4, 7, 6,
7770         1, 0, 2, 1, 2, 3,
7771 };
7772
7773 #define BBOXEDGES 13
7774 static const float bboxedges[BBOXEDGES][6] = 
7775 {
7776         // whole box
7777         { 0, 0, 0, 1, 1, 1 },
7778         // bottom edges
7779         { 0, 0, 0, 0, 1, 0 },
7780         { 0, 0, 0, 1, 0, 0 },
7781         { 0, 1, 0, 1, 1, 0 },
7782         { 1, 0, 0, 1, 1, 0 },
7783         // top edges
7784         { 0, 0, 1, 0, 1, 1 },
7785         { 0, 0, 1, 1, 0, 1 },
7786         { 0, 1, 1, 1, 1, 1 },
7787         { 1, 0, 1, 1, 1, 1 },
7788         // vertical edges
7789         { 0, 0, 0, 0, 0, 1 },
7790         { 1, 0, 0, 1, 0, 1 },
7791         { 0, 1, 0, 0, 1, 1 },
7792         { 1, 1, 0, 1, 1, 1 },
7793 };
7794
7795 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7796 {
7797         int numvertices = BBOXEDGES * 8;
7798         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7799         int numtriangles = BBOXEDGES * 12;
7800         unsigned short elements[BBOXEDGES * 36];
7801         int i, edge;
7802         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7803
7804         RSurf_ActiveWorldEntity();
7805
7806         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7807         GL_DepthMask(false);
7808         GL_DepthRange(0, 1);
7809         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7810
7811         for (edge = 0; edge < BBOXEDGES; edge++)
7812         {
7813                 for (i = 0; i < 3; i++)
7814                 {
7815                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7816                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7817                 }
7818                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7819                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7820                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7821                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7822                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7823                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7824                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7825                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7826                 for (i = 0; i < 36; i++)
7827                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7828         }
7829         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7830         if (r_refdef.fogenabled)
7831         {
7832                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7833                 {
7834                         f1 = RSurf_FogVertex(v);
7835                         f2 = 1 - f1;
7836                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7837                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7838                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7839                 }
7840         }
7841         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7842         R_Mesh_ResetTextureState();
7843         R_SetupShader_Generic_NoTexture(false, false);
7844         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7845 }
7846
7847 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7848 {
7849         // hacky overloading of the parameters
7850         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7851         int i;
7852         float color[4];
7853         prvm_edict_t *edict;
7854
7855         GL_CullFace(GL_NONE);
7856         R_SetupShader_Generic_NoTexture(false, false);
7857
7858         for (i = 0;i < numsurfaces;i++)
7859         {
7860                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7861                 switch ((int)PRVM_serveredictfloat(edict, solid))
7862                 {
7863                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7864                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7865                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7866                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7867                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7868                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7869                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7870                 }
7871                 if (prog == CLVM_prog)
7872                         color[3] *= r_showbboxes_client.value;
7873                 else
7874                         color[3] *= r_showbboxes.value;
7875                 color[3] = bound(0, color[3], 1);
7876                 GL_DepthTest(!r_showdisabledepthtest.integer);
7877                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7878         }
7879 }
7880
7881 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7882 {
7883         int i;
7884         prvm_edict_t *edict;
7885         vec3_t center;
7886
7887         if (prog == NULL)
7888                 return;
7889
7890         for (i = 0; i < prog->num_edicts; i++)
7891         {
7892                 edict = PRVM_EDICT_NUM(i);
7893                 if (edict->priv.server->free)
7894                         continue;
7895                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7896                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7897                         continue;
7898                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7899                         continue;
7900                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7901                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7902         }
7903 }
7904
7905 static const int nomodelelement3i[24] =
7906 {
7907         5, 2, 0,
7908         5, 1, 2,
7909         5, 0, 3,
7910         5, 3, 1,
7911         0, 2, 4,
7912         2, 1, 4,
7913         3, 0, 4,
7914         1, 3, 4
7915 };
7916
7917 static const unsigned short nomodelelement3s[24] =
7918 {
7919         5, 2, 0,
7920         5, 1, 2,
7921         5, 0, 3,
7922         5, 3, 1,
7923         0, 2, 4,
7924         2, 1, 4,
7925         3, 0, 4,
7926         1, 3, 4
7927 };
7928
7929 static const float nomodelvertex3f[6*3] =
7930 {
7931         -16,   0,   0,
7932          16,   0,   0,
7933           0, -16,   0,
7934           0,  16,   0,
7935           0,   0, -16,
7936           0,   0,  16
7937 };
7938
7939 static const float nomodelcolor4f[6*4] =
7940 {
7941         0.0f, 0.0f, 0.5f, 1.0f,
7942         0.0f, 0.0f, 0.5f, 1.0f,
7943         0.0f, 0.5f, 0.0f, 1.0f,
7944         0.0f, 0.5f, 0.0f, 1.0f,
7945         0.5f, 0.0f, 0.0f, 1.0f,
7946         0.5f, 0.0f, 0.0f, 1.0f
7947 };
7948
7949 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7950 {
7951         int i;
7952         float f1, f2, *c;
7953         float color4f[6*4];
7954
7955         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);
7956
7957         // this is only called once per entity so numsurfaces is always 1, and
7958         // surfacelist is always {0}, so this code does not handle batches
7959
7960         if (rsurface.ent_flags & RENDER_ADDITIVE)
7961         {
7962                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7963                 GL_DepthMask(false);
7964         }
7965         else if (rsurface.colormod[3] < 1)
7966         {
7967                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7968                 GL_DepthMask(false);
7969         }
7970         else
7971         {
7972                 GL_BlendFunc(GL_ONE, GL_ZERO);
7973                 GL_DepthMask(true);
7974         }
7975         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7976         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7977         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7978         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7979         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7980         for (i = 0, c = color4f;i < 6;i++, c += 4)
7981         {
7982                 c[0] *= rsurface.colormod[0];
7983                 c[1] *= rsurface.colormod[1];
7984                 c[2] *= rsurface.colormod[2];
7985                 c[3] *= rsurface.colormod[3];
7986         }
7987         if (r_refdef.fogenabled)
7988         {
7989                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7990                 {
7991                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7992                         f2 = 1 - f1;
7993                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7994                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7995                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7996                 }
7997         }
7998 //      R_Mesh_ResetTextureState();
7999         R_SetupShader_Generic_NoTexture(false, false);
8000         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8001         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8002 }
8003
8004 void R_DrawNoModel(entity_render_t *ent)
8005 {
8006         vec3_t org;
8007         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8008         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8009                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8010         else
8011                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8012 }
8013
8014 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
8015 {
8016         vec3_t right1, right2, diff, normal;
8017
8018         VectorSubtract (org2, org1, normal);
8019
8020         // calculate 'right' vector for start
8021         VectorSubtract (r_refdef.view.origin, org1, diff);
8022         CrossProduct (normal, diff, right1);
8023         VectorNormalize (right1);
8024
8025         // calculate 'right' vector for end
8026         VectorSubtract (r_refdef.view.origin, org2, diff);
8027         CrossProduct (normal, diff, right2);
8028         VectorNormalize (right2);
8029
8030         vert[ 0] = org1[0] + width * right1[0];
8031         vert[ 1] = org1[1] + width * right1[1];
8032         vert[ 2] = org1[2] + width * right1[2];
8033         vert[ 3] = org1[0] - width * right1[0];
8034         vert[ 4] = org1[1] - width * right1[1];
8035         vert[ 5] = org1[2] - width * right1[2];
8036         vert[ 6] = org2[0] - width * right2[0];
8037         vert[ 7] = org2[1] - width * right2[1];
8038         vert[ 8] = org2[2] - width * right2[2];
8039         vert[ 9] = org2[0] + width * right2[0];
8040         vert[10] = org2[1] + width * right2[1];
8041         vert[11] = org2[2] + width * right2[2];
8042 }
8043
8044 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)
8045 {
8046         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8047         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8048         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8049         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8050         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8051         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8052         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8053         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8054         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8055         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8056         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8057         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8058 }
8059
8060 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8061 {
8062         int i;
8063         float *vertex3f;
8064         float v[3];
8065         VectorSet(v, x, y, z);
8066         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8067                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8068                         break;
8069         if (i == mesh->numvertices)
8070         {
8071                 if (mesh->numvertices < mesh->maxvertices)
8072                 {
8073                         VectorCopy(v, vertex3f);
8074                         mesh->numvertices++;
8075                 }
8076                 return mesh->numvertices;
8077         }
8078         else
8079                 return i;
8080 }
8081
8082 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8083 {
8084         int i;
8085         int *e, element[3];
8086         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8087         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8088         e = mesh->element3i + mesh->numtriangles * 3;
8089         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8090         {
8091                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8092                 if (mesh->numtriangles < mesh->maxtriangles)
8093                 {
8094                         *e++ = element[0];
8095                         *e++ = element[1];
8096                         *e++ = element[2];
8097                         mesh->numtriangles++;
8098                 }
8099                 element[1] = element[2];
8100         }
8101 }
8102
8103 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8104 {
8105         int i;
8106         int *e, element[3];
8107         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8108         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8109         e = mesh->element3i + mesh->numtriangles * 3;
8110         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8111         {
8112                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8113                 if (mesh->numtriangles < mesh->maxtriangles)
8114                 {
8115                         *e++ = element[0];
8116                         *e++ = element[1];
8117                         *e++ = element[2];
8118                         mesh->numtriangles++;
8119                 }
8120                 element[1] = element[2];
8121         }
8122 }
8123
8124 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8125 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8126 {
8127         int planenum, planenum2;
8128         int w;
8129         int tempnumpoints;
8130         mplane_t *plane, *plane2;
8131         double maxdist;
8132         double temppoints[2][256*3];
8133         // figure out how large a bounding box we need to properly compute this brush
8134         maxdist = 0;
8135         for (w = 0;w < numplanes;w++)
8136                 maxdist = max(maxdist, fabs(planes[w].dist));
8137         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8138         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8139         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8140         {
8141                 w = 0;
8142                 tempnumpoints = 4;
8143                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8144                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8145                 {
8146                         if (planenum2 == planenum)
8147                                 continue;
8148                         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);
8149                         w = !w;
8150                 }
8151                 if (tempnumpoints < 3)
8152                         continue;
8153                 // generate elements forming a triangle fan for this polygon
8154                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8155         }
8156 }
8157
8158 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)
8159 {
8160         texturelayer_t *layer;
8161         layer = t->currentlayers + t->currentnumlayers++;
8162         layer->type = type;
8163         layer->depthmask = depthmask;
8164         layer->blendfunc1 = blendfunc1;
8165         layer->blendfunc2 = blendfunc2;
8166         layer->texture = texture;
8167         layer->texmatrix = *matrix;
8168         layer->color[0] = r;
8169         layer->color[1] = g;
8170         layer->color[2] = b;
8171         layer->color[3] = a;
8172 }
8173
8174 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8175 {
8176         if(parms[0] == 0 && parms[1] == 0)
8177                 return false;
8178         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8179                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8180                         return false;
8181         return true;
8182 }
8183
8184 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8185 {
8186         double index, f;
8187         index = parms[2] + rsurface.shadertime * parms[3];
8188         index -= floor(index);
8189         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8190         {
8191         default:
8192         case Q3WAVEFUNC_NONE:
8193         case Q3WAVEFUNC_NOISE:
8194         case Q3WAVEFUNC_COUNT:
8195                 f = 0;
8196                 break;
8197         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8198         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8199         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8200         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8201         case Q3WAVEFUNC_TRIANGLE:
8202                 index *= 4;
8203                 f = index - floor(index);
8204                 if (index < 1)
8205                 {
8206                         // f = f;
8207                 }
8208                 else if (index < 2)
8209                         f = 1 - f;
8210                 else if (index < 3)
8211                         f = -f;
8212                 else
8213                         f = -(1 - f);
8214                 break;
8215         }
8216         f = parms[0] + parms[1] * f;
8217         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8218                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8219         return (float) f;
8220 }
8221
8222 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8223 {
8224         int w, h, idx;
8225         float shadertime;
8226         float f;
8227         float offsetd[2];
8228         float tcmat[12];
8229         matrix4x4_t matrix, temp;
8230         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8231         // it's better to have one huge fixup every 9 hours than gradual
8232         // degradation over time which looks consistently bad after many hours.
8233         //
8234         // tcmod scroll in particular suffers from this degradation which can't be
8235         // effectively worked around even with floor() tricks because we don't
8236         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8237         // a workaround involving floor() would be incorrect anyway...
8238         shadertime = rsurface.shadertime;
8239         if (shadertime >= 32768.0f)
8240                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8241         switch(tcmod->tcmod)
8242         {
8243                 case Q3TCMOD_COUNT:
8244                 case Q3TCMOD_NONE:
8245                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8246                                 matrix = r_waterscrollmatrix;
8247                         else
8248                                 matrix = identitymatrix;
8249                         break;
8250                 case Q3TCMOD_ENTITYTRANSLATE:
8251                         // this is used in Q3 to allow the gamecode to control texcoord
8252                         // scrolling on the entity, which is not supported in darkplaces yet.
8253                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8254                         break;
8255                 case Q3TCMOD_ROTATE:
8256                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8257                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8258                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8259                         break;
8260                 case Q3TCMOD_SCALE:
8261                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8262                         break;
8263                 case Q3TCMOD_SCROLL:
8264                         // this particular tcmod is a "bug for bug" compatible one with regards to
8265                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8266                         // specifically did the wrapping and so we must mimic that...
8267                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8268                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8269                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8270                         break;
8271                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8272                         w = (int) tcmod->parms[0];
8273                         h = (int) tcmod->parms[1];
8274                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8275                         f = f - floor(f);
8276                         idx = (int) floor(f * w * h);
8277                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8278                         break;
8279                 case Q3TCMOD_STRETCH:
8280                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8281                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8282                         break;
8283                 case Q3TCMOD_TRANSFORM:
8284                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8285                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8286                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8287                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8288                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8289                         break;
8290                 case Q3TCMOD_TURBULENT:
8291                         // this is handled in the RSurf_PrepareVertices function
8292                         matrix = identitymatrix;
8293                         break;
8294         }
8295         temp = *texmatrix;
8296         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8297 }
8298
8299 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8300 {
8301         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8302         char name[MAX_QPATH];
8303         skinframe_t *skinframe;
8304         unsigned char pixels[296*194];
8305         strlcpy(cache->name, skinname, sizeof(cache->name));
8306         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8307         if (developer_loading.integer)
8308                 Con_Printf("loading %s\n", name);
8309         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8310         if (!skinframe || !skinframe->base)
8311         {
8312                 unsigned char *f;
8313                 fs_offset_t filesize;
8314                 skinframe = NULL;
8315                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8316                 if (f)
8317                 {
8318                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8319                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8320                         Mem_Free(f);
8321                 }
8322         }
8323         cache->skinframe = skinframe;
8324 }
8325
8326 texture_t *R_GetCurrentTexture(texture_t *t)
8327 {
8328         int i;
8329         const entity_render_t *ent = rsurface.entity;
8330         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8331         q3shaderinfo_layer_tcmod_t *tcmod;
8332
8333         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8334                 return t->currentframe;
8335         t->update_lastrenderframe = r_textureframe;
8336         t->update_lastrenderentity = (void *)ent;
8337
8338         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8339                 t->camera_entity = ent->entitynumber;
8340         else
8341                 t->camera_entity = 0;
8342
8343         // switch to an alternate material if this is a q1bsp animated material
8344         {
8345                 texture_t *texture = t;
8346                 int s = rsurface.ent_skinnum;
8347                 if ((unsigned int)s >= (unsigned int)model->numskins)
8348                         s = 0;
8349                 if (model->skinscenes)
8350                 {
8351                         if (model->skinscenes[s].framecount > 1)
8352                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8353                         else
8354                                 s = model->skinscenes[s].firstframe;
8355                 }
8356                 if (s > 0)
8357                         t = t + s * model->num_surfaces;
8358                 if (t->animated)
8359                 {
8360                         // use an alternate animation if the entity's frame is not 0,
8361                         // and only if the texture has an alternate animation
8362                         if (t->animated == 2) // q2bsp
8363                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8364                         else if (rsurface.ent_alttextures && t->anim_total[1])
8365                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8366                         else
8367                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8368                 }
8369                 texture->currentframe = t;
8370         }
8371
8372         // update currentskinframe to be a qw skin or animation frame
8373         if (rsurface.ent_qwskin >= 0)
8374         {
8375                 i = rsurface.ent_qwskin;
8376                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8377                 {
8378                         r_qwskincache_size = cl.maxclients;
8379                         if (r_qwskincache)
8380                                 Mem_Free(r_qwskincache);
8381                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8382                 }
8383                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8384                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8385                 t->currentskinframe = r_qwskincache[i].skinframe;
8386                 if (t->materialshaderpass && t->currentskinframe == NULL)
8387                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8388         }
8389         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8390                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8391         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8392                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8393
8394         t->currentmaterialflags = t->basematerialflags;
8395         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8396         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8397                 t->currentalpha *= r_wateralpha.value;
8398         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8399                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8400         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8401                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8402         if (!(rsurface.ent_flags & RENDER_LIGHT))
8403                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8404         else if (FAKELIGHT_ENABLED)
8405         {
8406                 // no modellight if using fakelight for the map
8407         }
8408         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8409         {
8410                 // pick a model lighting mode
8411                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8412                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8413                 else
8414                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8415         }
8416         if (rsurface.ent_flags & RENDER_ADDITIVE)
8417                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8418         else if (t->currentalpha < 1)
8419                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8420         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8421         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8422                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8423         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8424                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8425         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8426                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8427         if (t->backgroundshaderpass)
8428                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8429         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8430         {
8431                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8432                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8433         }
8434         else
8435                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8436         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8437         {
8438                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8439                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8440         }
8441         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8442                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8443
8444         // there is no tcmod
8445         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8446         {
8447                 t->currenttexmatrix = r_waterscrollmatrix;
8448                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8449         }
8450         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8451         {
8452                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8453                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8454         }
8455
8456         if (t->materialshaderpass)
8457                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8458                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8459
8460         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8461         if (t->currentskinframe->qpixels)
8462                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8463         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8464         if (!t->basetexture)
8465                 t->basetexture = r_texture_notexture;
8466         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8467         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8468         t->nmaptexture = t->currentskinframe->nmap;
8469         if (!t->nmaptexture)
8470                 t->nmaptexture = r_texture_blanknormalmap;
8471         t->glosstexture = r_texture_black;
8472         t->glowtexture = t->currentskinframe->glow;
8473         t->fogtexture = t->currentskinframe->fog;
8474         t->reflectmasktexture = t->currentskinframe->reflect;
8475         if (t->backgroundshaderpass)
8476         {
8477                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8478                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8479                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8480                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8481                 t->backgroundglosstexture = r_texture_black;
8482                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8483                 if (!t->backgroundnmaptexture)
8484                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8485                 // make sure that if glow is going to be used, both textures are not NULL
8486                 if (!t->backgroundglowtexture && t->glowtexture)
8487                         t->backgroundglowtexture = r_texture_black;
8488                 if (!t->glowtexture && t->backgroundglowtexture)
8489                         t->glowtexture = r_texture_black;
8490         }
8491         else
8492         {
8493                 t->backgroundbasetexture = r_texture_white;
8494                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8495                 t->backgroundglosstexture = r_texture_black;
8496                 t->backgroundglowtexture = NULL;
8497         }
8498         t->specularpower = r_shadow_glossexponent.value;
8499         // TODO: store reference values for these in the texture?
8500         t->specularscale = 0;
8501         if (r_shadow_gloss.integer > 0)
8502         {
8503                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8504                 {
8505                         if (r_shadow_glossintensity.value > 0)
8506                         {
8507                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8508                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8509                                 t->specularscale = r_shadow_glossintensity.value;
8510                         }
8511                 }
8512                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8513                 {
8514                         t->glosstexture = r_texture_white;
8515                         t->backgroundglosstexture = r_texture_white;
8516                         t->specularscale = r_shadow_gloss2intensity.value;
8517                         t->specularpower = r_shadow_gloss2exponent.value;
8518                 }
8519         }
8520         t->specularscale *= t->specularscalemod;
8521         t->specularpower *= t->specularpowermod;
8522         t->rtlightambient = 0;
8523
8524         // lightmaps mode looks bad with dlights using actual texturing, so turn
8525         // off the colormap and glossmap, but leave the normalmap on as it still
8526         // accurately represents the shading involved
8527         if (gl_lightmaps.integer)
8528         {
8529                 t->basetexture = r_texture_grey128;
8530                 t->pantstexture = r_texture_black;
8531                 t->shirttexture = r_texture_black;
8532                 if (gl_lightmaps.integer < 2)
8533                         t->nmaptexture = r_texture_blanknormalmap;
8534                 t->glosstexture = r_texture_black;
8535                 t->glowtexture = NULL;
8536                 t->fogtexture = NULL;
8537                 t->reflectmasktexture = NULL;
8538                 t->backgroundbasetexture = NULL;
8539                 if (gl_lightmaps.integer < 2)
8540                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8541                 t->backgroundglosstexture = r_texture_black;
8542                 t->backgroundglowtexture = NULL;
8543                 t->specularscale = 0;
8544                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8545         }
8546
8547         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8548         VectorClear(t->dlightcolor);
8549         t->currentnumlayers = 0;
8550         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8551         {
8552                 int blendfunc1, blendfunc2;
8553                 qboolean depthmask;
8554                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8555                 {
8556                         blendfunc1 = GL_SRC_ALPHA;
8557                         blendfunc2 = GL_ONE;
8558                 }
8559                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8560                 {
8561                         blendfunc1 = GL_SRC_ALPHA;
8562                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8563                 }
8564                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8565                 {
8566                         blendfunc1 = t->customblendfunc[0];
8567                         blendfunc2 = t->customblendfunc[1];
8568                 }
8569                 else
8570                 {
8571                         blendfunc1 = GL_ONE;
8572                         blendfunc2 = GL_ZERO;
8573                 }
8574                 // don't colormod evilblend textures
8575                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8576                         VectorSet(t->lightmapcolor, 1, 1, 1);
8577                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8578                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8579                 {
8580                         // fullbright is not affected by r_refdef.lightmapintensity
8581                         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]);
8582                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8583                                 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]);
8584                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8585                                 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]);
8586                 }
8587                 else
8588                 {
8589                         vec3_t ambientcolor;
8590                         float colorscale;
8591                         // set the color tint used for lights affecting this surface
8592                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8593                         colorscale = 2;
8594                         // q3bsp has no lightmap updates, so the lightstylevalue that
8595                         // would normally be baked into the lightmap must be
8596                         // applied to the color
8597                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8598                         if (model->type == mod_brushq3)
8599                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8600                         colorscale *= r_refdef.lightmapintensity;
8601                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8602                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8603                         // basic lit geometry
8604                         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]);
8605                         // add pants/shirt if needed
8606                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8607                                 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]);
8608                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8609                                 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]);
8610                         // now add ambient passes if needed
8611                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8612                         {
8613                                 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]);
8614                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8615                                         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]);
8616                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8617                                         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]);
8618                         }
8619                 }
8620                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8621                         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]);
8622                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8623                 {
8624                         // if this is opaque use alpha blend which will darken the earlier
8625                         // passes cheaply.
8626                         //
8627                         // if this is an alpha blended material, all the earlier passes
8628                         // were darkened by fog already, so we only need to add the fog
8629                         // color ontop through the fog mask texture
8630                         //
8631                         // if this is an additive blended material, all the earlier passes
8632                         // were darkened by fog already, and we should not add fog color
8633                         // (because the background was not darkened, there is no fog color
8634                         // that was lost behind it).
8635                         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]);
8636                 }
8637         }
8638
8639         return t;
8640 }
8641
8642 rsurfacestate_t rsurface;
8643
8644 void RSurf_ActiveWorldEntity(void)
8645 {
8646         dp_model_t *model = r_refdef.scene.worldmodel;
8647         //if (rsurface.entity == r_refdef.scene.worldentity)
8648         //      return;
8649         rsurface.entity = r_refdef.scene.worldentity;
8650         rsurface.skeleton = NULL;
8651         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8652         rsurface.ent_skinnum = 0;
8653         rsurface.ent_qwskin = -1;
8654         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8655         rsurface.shadertime = r_refdef.scene.time;
8656         rsurface.matrix = identitymatrix;
8657         rsurface.inversematrix = identitymatrix;
8658         rsurface.matrixscale = 1;
8659         rsurface.inversematrixscale = 1;
8660         R_EntityMatrix(&identitymatrix);
8661         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8662         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8663         rsurface.fograngerecip = r_refdef.fograngerecip;
8664         rsurface.fogheightfade = r_refdef.fogheightfade;
8665         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8666         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8667         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8668         {
8669                 R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir);
8670                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8671         }
8672         else
8673         {
8674                 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8675                 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8676                 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8677         }
8678         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8679         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8680         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8681         rsurface.colormod[3] = 1;
8682         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);
8683         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8684         rsurface.frameblend[0].lerp = 1;
8685         rsurface.ent_alttextures = false;
8686         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8687         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8688         rsurface.entityskeletaltransform3x4 = NULL;
8689         rsurface.entityskeletaltransform3x4buffer = NULL;
8690         rsurface.entityskeletaltransform3x4offset = 0;
8691         rsurface.entityskeletaltransform3x4size = 0;;
8692         rsurface.entityskeletalnumtransforms = 0;
8693         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8694         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8695         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8696         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8697         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8698         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8699         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8700         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8701         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8702         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8703         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8704         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8705         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8706         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8707         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8708         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8709         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8710         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8711         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8712         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8714         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8715         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8716         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8717         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8718         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8720         rsurface.modelelement3i = model->surfmesh.data_element3i;
8721         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8722         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8723         rsurface.modelelement3s = model->surfmesh.data_element3s;
8724         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8725         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8726         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8727         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8728         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8729         rsurface.modelsurfaces = model->data_surfaces;
8730         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8731         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8732         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8733         rsurface.modelgeneratedvertex = false;
8734         rsurface.batchgeneratedvertex = false;
8735         rsurface.batchfirstvertex = 0;
8736         rsurface.batchnumvertices = 0;
8737         rsurface.batchfirsttriangle = 0;
8738         rsurface.batchnumtriangles = 0;
8739         rsurface.batchvertex3f  = NULL;
8740         rsurface.batchvertex3f_vertexbuffer = NULL;
8741         rsurface.batchvertex3f_bufferoffset = 0;
8742         rsurface.batchsvector3f = NULL;
8743         rsurface.batchsvector3f_vertexbuffer = NULL;
8744         rsurface.batchsvector3f_bufferoffset = 0;
8745         rsurface.batchtvector3f = NULL;
8746         rsurface.batchtvector3f_vertexbuffer = NULL;
8747         rsurface.batchtvector3f_bufferoffset = 0;
8748         rsurface.batchnormal3f  = NULL;
8749         rsurface.batchnormal3f_vertexbuffer = NULL;
8750         rsurface.batchnormal3f_bufferoffset = 0;
8751         rsurface.batchlightmapcolor4f = NULL;
8752         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8753         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8754         rsurface.batchtexcoordtexture2f = NULL;
8755         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8756         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8757         rsurface.batchtexcoordlightmap2f = NULL;
8758         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8759         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8760         rsurface.batchskeletalindex4ub = NULL;
8761         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8762         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8763         rsurface.batchskeletalweight4ub = NULL;
8764         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8765         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8766         rsurface.batchvertexmesh = NULL;
8767         rsurface.batchvertexmesh_vertexbuffer = NULL;
8768         rsurface.batchvertexmesh_bufferoffset = 0;
8769         rsurface.batchelement3i = NULL;
8770         rsurface.batchelement3i_indexbuffer = NULL;
8771         rsurface.batchelement3i_bufferoffset = 0;
8772         rsurface.batchelement3s = NULL;
8773         rsurface.batchelement3s_indexbuffer = NULL;
8774         rsurface.batchelement3s_bufferoffset = 0;
8775         rsurface.passcolor4f = NULL;
8776         rsurface.passcolor4f_vertexbuffer = NULL;
8777         rsurface.passcolor4f_bufferoffset = 0;
8778         rsurface.forcecurrenttextureupdate = false;
8779 }
8780
8781 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8782 {
8783         dp_model_t *model = ent->model;
8784         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8785         //      return;
8786         rsurface.entity = (entity_render_t *)ent;
8787         rsurface.skeleton = ent->skeleton;
8788         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8789         rsurface.ent_skinnum = ent->skinnum;
8790         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;
8791         rsurface.ent_flags = ent->flags;
8792         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8793         {
8794                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8795         }
8796         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8797         rsurface.matrix = ent->matrix;
8798         rsurface.inversematrix = ent->inversematrix;
8799         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8800         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8801         R_EntityMatrix(&rsurface.matrix);
8802         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8803         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8804         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8805         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8806         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8807         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8808         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8809         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8810         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8811         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8812         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8813         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8814         rsurface.colormod[3] = ent->alpha;
8815         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8816         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8817         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8818         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8819         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8820         if (ent->model->brush.submodel && !prepass)
8821         {
8822                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8823                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8824         }
8825         // if the animcache code decided it should use the shader path, skip the deform step
8826         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8827         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8828         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8829         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8830         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8831         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8832         {
8833                 if (ent->animcache_vertex3f)
8834                 {
8835                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8836                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8837                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8838                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8839                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8840                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8841                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8842                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8843                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8844                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8845                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8846                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8847                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8848                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8849                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8850                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8851                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8852                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8853                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8854                 }
8855                 else if (wanttangents)
8856                 {
8857                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8858                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8859                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8860                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8861                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8862                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8863                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8864                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8865                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8866                         rsurface.modelvertexmesh = NULL;
8867                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8868                         rsurface.modelvertexmesh_bufferoffset = 0;
8869                         rsurface.modelvertex3f_vertexbuffer = NULL;
8870                         rsurface.modelvertex3f_bufferoffset = 0;
8871                         rsurface.modelvertex3f_vertexbuffer = 0;
8872                         rsurface.modelvertex3f_bufferoffset = 0;
8873                         rsurface.modelsvector3f_vertexbuffer = 0;
8874                         rsurface.modelsvector3f_bufferoffset = 0;
8875                         rsurface.modeltvector3f_vertexbuffer = 0;
8876                         rsurface.modeltvector3f_bufferoffset = 0;
8877                         rsurface.modelnormal3f_vertexbuffer = 0;
8878                         rsurface.modelnormal3f_bufferoffset = 0;
8879                 }
8880                 else if (wantnormals)
8881                 {
8882                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8883                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8884                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8885                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8886                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8887                         rsurface.modelsvector3f = NULL;
8888                         rsurface.modeltvector3f = NULL;
8889                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8890                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8891                         rsurface.modelvertexmesh = NULL;
8892                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8893                         rsurface.modelvertexmesh_bufferoffset = 0;
8894                         rsurface.modelvertex3f_vertexbuffer = NULL;
8895                         rsurface.modelvertex3f_bufferoffset = 0;
8896                         rsurface.modelvertex3f_vertexbuffer = 0;
8897                         rsurface.modelvertex3f_bufferoffset = 0;
8898                         rsurface.modelsvector3f_vertexbuffer = 0;
8899                         rsurface.modelsvector3f_bufferoffset = 0;
8900                         rsurface.modeltvector3f_vertexbuffer = 0;
8901                         rsurface.modeltvector3f_bufferoffset = 0;
8902                         rsurface.modelnormal3f_vertexbuffer = 0;
8903                         rsurface.modelnormal3f_bufferoffset = 0;
8904                 }
8905                 else
8906                 {
8907                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8908                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8909                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8910                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8911                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8912                         rsurface.modelsvector3f = NULL;
8913                         rsurface.modeltvector3f = NULL;
8914                         rsurface.modelnormal3f = NULL;
8915                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8916                         rsurface.modelvertexmesh = NULL;
8917                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8918                         rsurface.modelvertexmesh_bufferoffset = 0;
8919                         rsurface.modelvertex3f_vertexbuffer = NULL;
8920                         rsurface.modelvertex3f_bufferoffset = 0;
8921                         rsurface.modelvertex3f_vertexbuffer = 0;
8922                         rsurface.modelvertex3f_bufferoffset = 0;
8923                         rsurface.modelsvector3f_vertexbuffer = 0;
8924                         rsurface.modelsvector3f_bufferoffset = 0;
8925                         rsurface.modeltvector3f_vertexbuffer = 0;
8926                         rsurface.modeltvector3f_bufferoffset = 0;
8927                         rsurface.modelnormal3f_vertexbuffer = 0;
8928                         rsurface.modelnormal3f_bufferoffset = 0;
8929                 }
8930                 rsurface.modelgeneratedvertex = true;
8931         }
8932         else
8933         {
8934                 if (rsurface.entityskeletaltransform3x4)
8935                 {
8936                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8937                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8938                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8939                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8940                 }
8941                 else
8942                 {
8943                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8944                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8945                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8946                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8947                 }
8948                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8949                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8950                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8951                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8952                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8953                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8954                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8955                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8956                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8957                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8958                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8959                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8960                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8961                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8962                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8963                 rsurface.modelgeneratedvertex = false;
8964         }
8965         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8966         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8967         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8968         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8969         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8970         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8971         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8972         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8973         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8974         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8975         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8976         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8977         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8978         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8979         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8980         rsurface.modelelement3i = model->surfmesh.data_element3i;
8981         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8982         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8983         rsurface.modelelement3s = model->surfmesh.data_element3s;
8984         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8985         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8986         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8987         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8988         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8989         rsurface.modelsurfaces = model->data_surfaces;
8990         rsurface.batchgeneratedvertex = false;
8991         rsurface.batchfirstvertex = 0;
8992         rsurface.batchnumvertices = 0;
8993         rsurface.batchfirsttriangle = 0;
8994         rsurface.batchnumtriangles = 0;
8995         rsurface.batchvertex3f  = NULL;
8996         rsurface.batchvertex3f_vertexbuffer = NULL;
8997         rsurface.batchvertex3f_bufferoffset = 0;
8998         rsurface.batchsvector3f = NULL;
8999         rsurface.batchsvector3f_vertexbuffer = NULL;
9000         rsurface.batchsvector3f_bufferoffset = 0;
9001         rsurface.batchtvector3f = NULL;
9002         rsurface.batchtvector3f_vertexbuffer = NULL;
9003         rsurface.batchtvector3f_bufferoffset = 0;
9004         rsurface.batchnormal3f  = NULL;
9005         rsurface.batchnormal3f_vertexbuffer = NULL;
9006         rsurface.batchnormal3f_bufferoffset = 0;
9007         rsurface.batchlightmapcolor4f = NULL;
9008         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9009         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9010         rsurface.batchtexcoordtexture2f = NULL;
9011         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9012         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9013         rsurface.batchtexcoordlightmap2f = NULL;
9014         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9015         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9016         rsurface.batchskeletalindex4ub = NULL;
9017         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9018         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9019         rsurface.batchskeletalweight4ub = NULL;
9020         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9021         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9022         rsurface.batchvertexmesh = NULL;
9023         rsurface.batchvertexmesh_vertexbuffer = NULL;
9024         rsurface.batchvertexmesh_bufferoffset = 0;
9025         rsurface.batchelement3i = NULL;
9026         rsurface.batchelement3i_indexbuffer = NULL;
9027         rsurface.batchelement3i_bufferoffset = 0;
9028         rsurface.batchelement3s = NULL;
9029         rsurface.batchelement3s_indexbuffer = NULL;
9030         rsurface.batchelement3s_bufferoffset = 0;
9031         rsurface.passcolor4f = NULL;
9032         rsurface.passcolor4f_vertexbuffer = NULL;
9033         rsurface.passcolor4f_bufferoffset = 0;
9034         rsurface.forcecurrenttextureupdate = false;
9035 }
9036
9037 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)
9038 {
9039         rsurface.entity = r_refdef.scene.worldentity;
9040         rsurface.skeleton = NULL;
9041         rsurface.ent_skinnum = 0;
9042         rsurface.ent_qwskin = -1;
9043         rsurface.ent_flags = entflags;
9044         rsurface.shadertime = r_refdef.scene.time - shadertime;
9045         rsurface.modelnumvertices = numvertices;
9046         rsurface.modelnumtriangles = numtriangles;
9047         rsurface.matrix = *matrix;
9048         rsurface.inversematrix = *inversematrix;
9049         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9050         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9051         R_EntityMatrix(&rsurface.matrix);
9052         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9053         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9054         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9055         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9056         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9057         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9058         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9059         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9060         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9061         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9062         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9063         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9064         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);
9065         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9066         rsurface.frameblend[0].lerp = 1;
9067         rsurface.ent_alttextures = false;
9068         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9069         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9070         rsurface.entityskeletaltransform3x4 = NULL;
9071         rsurface.entityskeletaltransform3x4buffer = NULL;
9072         rsurface.entityskeletaltransform3x4offset = 0;
9073         rsurface.entityskeletaltransform3x4size = 0;
9074         rsurface.entityskeletalnumtransforms = 0;
9075         r_refdef.stats[r_stat_batch_entitycustom_count]++;
9076         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9077         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9078         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9079         if (wanttangents)
9080         {
9081                 rsurface.modelvertex3f = (float *)vertex3f;
9082                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9083                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9084                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9085         }
9086         else if (wantnormals)
9087         {
9088                 rsurface.modelvertex3f = (float *)vertex3f;
9089                 rsurface.modelsvector3f = NULL;
9090                 rsurface.modeltvector3f = NULL;
9091                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9092         }
9093         else
9094         {
9095                 rsurface.modelvertex3f = (float *)vertex3f;
9096                 rsurface.modelsvector3f = NULL;
9097                 rsurface.modeltvector3f = NULL;
9098                 rsurface.modelnormal3f = NULL;
9099         }
9100         rsurface.modelvertexmesh = NULL;
9101         rsurface.modelvertexmesh_vertexbuffer = NULL;
9102         rsurface.modelvertexmesh_bufferoffset = 0;
9103         rsurface.modelvertex3f_vertexbuffer = 0;
9104         rsurface.modelvertex3f_bufferoffset = 0;
9105         rsurface.modelsvector3f_vertexbuffer = 0;
9106         rsurface.modelsvector3f_bufferoffset = 0;
9107         rsurface.modeltvector3f_vertexbuffer = 0;
9108         rsurface.modeltvector3f_bufferoffset = 0;
9109         rsurface.modelnormal3f_vertexbuffer = 0;
9110         rsurface.modelnormal3f_bufferoffset = 0;
9111         rsurface.modelgeneratedvertex = true;
9112         rsurface.modellightmapcolor4f  = (float *)color4f;
9113         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9114         rsurface.modellightmapcolor4f_bufferoffset = 0;
9115         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9116         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9117         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9118         rsurface.modeltexcoordlightmap2f  = NULL;
9119         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9120         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9121         rsurface.modelskeletalindex4ub = NULL;
9122         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9123         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9124         rsurface.modelskeletalweight4ub = NULL;
9125         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9126         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9127         rsurface.modelelement3i = (int *)element3i;
9128         rsurface.modelelement3i_indexbuffer = NULL;
9129         rsurface.modelelement3i_bufferoffset = 0;
9130         rsurface.modelelement3s = (unsigned short *)element3s;
9131         rsurface.modelelement3s_indexbuffer = NULL;
9132         rsurface.modelelement3s_bufferoffset = 0;
9133         rsurface.modellightmapoffsets = NULL;
9134         rsurface.modelsurfaces = NULL;
9135         rsurface.batchgeneratedvertex = false;
9136         rsurface.batchfirstvertex = 0;
9137         rsurface.batchnumvertices = 0;
9138         rsurface.batchfirsttriangle = 0;
9139         rsurface.batchnumtriangles = 0;
9140         rsurface.batchvertex3f  = NULL;
9141         rsurface.batchvertex3f_vertexbuffer = NULL;
9142         rsurface.batchvertex3f_bufferoffset = 0;
9143         rsurface.batchsvector3f = NULL;
9144         rsurface.batchsvector3f_vertexbuffer = NULL;
9145         rsurface.batchsvector3f_bufferoffset = 0;
9146         rsurface.batchtvector3f = NULL;
9147         rsurface.batchtvector3f_vertexbuffer = NULL;
9148         rsurface.batchtvector3f_bufferoffset = 0;
9149         rsurface.batchnormal3f  = NULL;
9150         rsurface.batchnormal3f_vertexbuffer = NULL;
9151         rsurface.batchnormal3f_bufferoffset = 0;
9152         rsurface.batchlightmapcolor4f = NULL;
9153         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9154         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9155         rsurface.batchtexcoordtexture2f = NULL;
9156         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158         rsurface.batchtexcoordlightmap2f = NULL;
9159         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9160         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9161         rsurface.batchskeletalindex4ub = NULL;
9162         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9163         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9164         rsurface.batchskeletalweight4ub = NULL;
9165         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9166         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9167         rsurface.batchvertexmesh = NULL;
9168         rsurface.batchvertexmesh_vertexbuffer = NULL;
9169         rsurface.batchvertexmesh_bufferoffset = 0;
9170         rsurface.batchelement3i = NULL;
9171         rsurface.batchelement3i_indexbuffer = NULL;
9172         rsurface.batchelement3i_bufferoffset = 0;
9173         rsurface.batchelement3s = NULL;
9174         rsurface.batchelement3s_indexbuffer = NULL;
9175         rsurface.batchelement3s_bufferoffset = 0;
9176         rsurface.passcolor4f = NULL;
9177         rsurface.passcolor4f_vertexbuffer = NULL;
9178         rsurface.passcolor4f_bufferoffset = 0;
9179         rsurface.forcecurrenttextureupdate = true;
9180
9181         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9182         {
9183                 if ((wantnormals || wanttangents) && !normal3f)
9184                 {
9185                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9186                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9187                 }
9188                 if (wanttangents && !svector3f)
9189                 {
9190                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9191                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9192                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9193                 }
9194         }
9195 }
9196
9197 float RSurf_FogPoint(const float *v)
9198 {
9199         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9200         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9201         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9202         float FogHeightFade = r_refdef.fogheightfade;
9203         float fogfrac;
9204         unsigned int fogmasktableindex;
9205         if (r_refdef.fogplaneviewabove)
9206                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9207         else
9208                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9209         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9210         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9211 }
9212
9213 float RSurf_FogVertex(const float *v)
9214 {
9215         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9216         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9217         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9218         float FogHeightFade = rsurface.fogheightfade;
9219         float fogfrac;
9220         unsigned int fogmasktableindex;
9221         if (r_refdef.fogplaneviewabove)
9222                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9223         else
9224                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9225         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9226         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9227 }
9228
9229 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9230 {
9231         int i;
9232         for (i = 0;i < numelements;i++)
9233                 outelement3i[i] = inelement3i[i] + adjust;
9234 }
9235
9236 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9237 extern cvar_t gl_vbo;
9238 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9239 {
9240         int deformindex;
9241         int firsttriangle;
9242         int numtriangles;
9243         int firstvertex;
9244         int endvertex;
9245         int numvertices;
9246         int surfacefirsttriangle;
9247         int surfacenumtriangles;
9248         int surfacefirstvertex;
9249         int surfaceendvertex;
9250         int surfacenumvertices;
9251         int batchnumsurfaces = texturenumsurfaces;
9252         int batchnumvertices;
9253         int batchnumtriangles;
9254         int needsupdate;
9255         int i, j;
9256         qboolean gaps;
9257         qboolean dynamicvertex;
9258         float amplitude;
9259         float animpos;
9260         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9261         float waveparms[4];
9262         unsigned char *ub;
9263         q3shaderinfo_deform_t *deform;
9264         const msurface_t *surface, *firstsurface;
9265         r_vertexmesh_t *vertexmesh;
9266         if (!texturenumsurfaces)
9267                 return;
9268         // find vertex range of this surface batch
9269         gaps = false;
9270         firstsurface = texturesurfacelist[0];
9271         firsttriangle = firstsurface->num_firsttriangle;
9272         batchnumvertices = 0;
9273         batchnumtriangles = 0;
9274         firstvertex = endvertex = firstsurface->num_firstvertex;
9275         for (i = 0;i < texturenumsurfaces;i++)
9276         {
9277                 surface = texturesurfacelist[i];
9278                 if (surface != firstsurface + i)
9279                         gaps = true;
9280                 surfacefirstvertex = surface->num_firstvertex;
9281                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9282                 surfacenumvertices = surface->num_vertices;
9283                 surfacenumtriangles = surface->num_triangles;
9284                 if (firstvertex > surfacefirstvertex)
9285                         firstvertex = surfacefirstvertex;
9286                 if (endvertex < surfaceendvertex)
9287                         endvertex = surfaceendvertex;
9288                 batchnumvertices += surfacenumvertices;
9289                 batchnumtriangles += surfacenumtriangles;
9290         }
9291
9292         r_refdef.stats[r_stat_batch_batches]++;
9293         if (gaps)
9294                 r_refdef.stats[r_stat_batch_withgaps]++;
9295         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9296         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9297         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9298
9299         // we now know the vertex range used, and if there are any gaps in it
9300         rsurface.batchfirstvertex = firstvertex;
9301         rsurface.batchnumvertices = endvertex - firstvertex;
9302         rsurface.batchfirsttriangle = firsttriangle;
9303         rsurface.batchnumtriangles = batchnumtriangles;
9304
9305         // this variable holds flags for which properties have been updated that
9306         // may require regenerating vertexmesh array...
9307         needsupdate = 0;
9308
9309         // check if any dynamic vertex processing must occur
9310         dynamicvertex = false;
9311
9312         // a cvar to force the dynamic vertex path to be taken, for debugging
9313         if (r_batch_debugdynamicvertexpath.integer)
9314         {
9315                 if (!dynamicvertex)
9316                 {
9317                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9318                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9319                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9320                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9321                 }
9322                 dynamicvertex = true;
9323         }
9324
9325         // if there is a chance of animated vertex colors, it's a dynamic batch
9326         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9327         {
9328                 if (!dynamicvertex)
9329                 {
9330                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9331                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9332                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9333                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9334                 }
9335                 dynamicvertex = true;
9336                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9337         }
9338
9339         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9340         {
9341                 switch (deform->deform)
9342                 {
9343                 default:
9344                 case Q3DEFORM_PROJECTIONSHADOW:
9345                 case Q3DEFORM_TEXT0:
9346                 case Q3DEFORM_TEXT1:
9347                 case Q3DEFORM_TEXT2:
9348                 case Q3DEFORM_TEXT3:
9349                 case Q3DEFORM_TEXT4:
9350                 case Q3DEFORM_TEXT5:
9351                 case Q3DEFORM_TEXT6:
9352                 case Q3DEFORM_TEXT7:
9353                 case Q3DEFORM_NONE:
9354                         break;
9355                 case Q3DEFORM_AUTOSPRITE:
9356                         if (!dynamicvertex)
9357                         {
9358                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9359                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9360                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9361                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9362                         }
9363                         dynamicvertex = true;
9364                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9365                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9366                         break;
9367                 case Q3DEFORM_AUTOSPRITE2:
9368                         if (!dynamicvertex)
9369                         {
9370                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9371                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9372                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9373                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9374                         }
9375                         dynamicvertex = true;
9376                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9377                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9378                         break;
9379                 case Q3DEFORM_NORMAL:
9380                         if (!dynamicvertex)
9381                         {
9382                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9383                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9384                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9385                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9386                         }
9387                         dynamicvertex = true;
9388                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9389                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9390                         break;
9391                 case Q3DEFORM_WAVE:
9392                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9393                                 break; // if wavefunc is a nop, ignore this transform
9394                         if (!dynamicvertex)
9395                         {
9396                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9397                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9398                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9399                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9400                         }
9401                         dynamicvertex = true;
9402                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9403                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9404                         break;
9405                 case Q3DEFORM_BULGE:
9406                         if (!dynamicvertex)
9407                         {
9408                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9409                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9410                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9411                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9412                         }
9413                         dynamicvertex = true;
9414                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9415                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9416                         break;
9417                 case Q3DEFORM_MOVE:
9418                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9419                                 break; // if wavefunc is a nop, ignore this transform
9420                         if (!dynamicvertex)
9421                         {
9422                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9423                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9424                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9425                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9426                         }
9427                         dynamicvertex = true;
9428                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9429                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9430                         break;
9431                 }
9432         }
9433         if (rsurface.texture->materialshaderpass)
9434         {
9435                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9436                 {
9437                 default:
9438                 case Q3TCGEN_TEXTURE:
9439                         break;
9440                 case Q3TCGEN_LIGHTMAP:
9441                         if (!dynamicvertex)
9442                         {
9443                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9444                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9445                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9446                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9447                         }
9448                         dynamicvertex = true;
9449                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9450                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9451                         break;
9452                 case Q3TCGEN_VECTOR:
9453                         if (!dynamicvertex)
9454                         {
9455                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9456                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9457                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9458                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9459                         }
9460                         dynamicvertex = true;
9461                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9462                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9463                         break;
9464                 case Q3TCGEN_ENVIRONMENT:
9465                         if (!dynamicvertex)
9466                         {
9467                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9468                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9469                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9470                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9471                         }
9472                         dynamicvertex = true;
9473                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9474                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9475                         break;
9476                 }
9477                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9478                 {
9479                         if (!dynamicvertex)
9480                         {
9481                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9482                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9483                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9484                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9485                         }
9486                         dynamicvertex = true;
9487                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9488                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9489                 }
9490         }
9491
9492         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9493         {
9494                 if (!dynamicvertex)
9495                 {
9496                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9497                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9498                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9499                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9500                 }
9501                 dynamicvertex = true;
9502                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9503         }
9504
9505         // when the model data has no vertex buffer (dynamic mesh), we need to
9506         // eliminate gaps
9507         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9508                 batchneed |= BATCHNEED_NOGAPS;
9509
9510         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9511         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9512         // we ensure this by treating the vertex batch as dynamic...
9513         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9514         {
9515                 if (!dynamicvertex)
9516                 {
9517                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9518                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9519                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9520                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9521                 }
9522                 dynamicvertex = true;
9523         }
9524
9525         if (dynamicvertex)
9526         {
9527                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9528                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9529                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9530                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9531                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9532                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9533                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9534                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9535         }
9536
9537         // if needsupdate, we have to do a dynamic vertex batch for sure
9538         if (needsupdate & batchneed)
9539         {
9540                 if (!dynamicvertex)
9541                 {
9542                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9543                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9544                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9545                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9546                 }
9547                 dynamicvertex = true;
9548         }
9549
9550         // see if we need to build vertexmesh from arrays
9551         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9552         {
9553                 if (!dynamicvertex)
9554                 {
9555                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9556                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9557                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9558                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9559                 }
9560                 dynamicvertex = true;
9561         }
9562
9563         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9564         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9565                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9566
9567         rsurface.batchvertex3f = rsurface.modelvertex3f;
9568         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9569         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9570         rsurface.batchsvector3f = rsurface.modelsvector3f;
9571         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9572         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9573         rsurface.batchtvector3f = rsurface.modeltvector3f;
9574         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9575         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9576         rsurface.batchnormal3f = rsurface.modelnormal3f;
9577         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9578         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9579         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9580         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9581         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9582         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9583         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9584         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9585         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9586         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9587         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9588         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9589         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9590         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9591         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9592         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9593         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9594         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9595         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9596         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9597         rsurface.batchelement3i = rsurface.modelelement3i;
9598         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9599         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9600         rsurface.batchelement3s = rsurface.modelelement3s;
9601         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9602         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9603         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9604         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9605         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9606         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9607         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9608
9609         // if any dynamic vertex processing has to occur in software, we copy the
9610         // entire surface list together before processing to rebase the vertices
9611         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9612         //
9613         // if any gaps exist and we do not have a static vertex buffer, we have to
9614         // copy the surface list together to avoid wasting upload bandwidth on the
9615         // vertices in the gaps.
9616         //
9617         // if gaps exist and we have a static vertex buffer, we can choose whether
9618         // to combine the index buffer ranges into one dynamic index buffer or
9619         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9620         //
9621         // in many cases the batch is reduced to one draw call.
9622
9623         rsurface.batchmultidraw = false;
9624         rsurface.batchmultidrawnumsurfaces = 0;
9625         rsurface.batchmultidrawsurfacelist = NULL;
9626
9627         if (!dynamicvertex)
9628         {
9629                 // static vertex data, just set pointers...
9630                 rsurface.batchgeneratedvertex = false;
9631                 // if there are gaps, we want to build a combined index buffer,
9632                 // otherwise use the original static buffer with an appropriate offset
9633                 if (gaps)
9634                 {
9635                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9636                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9637                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9638                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9639                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9640                         {
9641                                 rsurface.batchmultidraw = true;
9642                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9643                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9644                                 return;
9645                         }
9646                         // build a new triangle elements array for this batch
9647                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9648                         rsurface.batchfirsttriangle = 0;
9649                         numtriangles = 0;
9650                         for (i = 0;i < texturenumsurfaces;i++)
9651                         {
9652                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9653                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9654                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9655                                 numtriangles += surfacenumtriangles;
9656                         }
9657                         rsurface.batchelement3i_indexbuffer = NULL;
9658                         rsurface.batchelement3i_bufferoffset = 0;
9659                         rsurface.batchelement3s = NULL;
9660                         rsurface.batchelement3s_indexbuffer = NULL;
9661                         rsurface.batchelement3s_bufferoffset = 0;
9662                         if (endvertex <= 65536)
9663                         {
9664                                 // make a 16bit (unsigned short) index array if possible
9665                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9666                                 for (i = 0;i < numtriangles*3;i++)
9667                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9668                         }
9669                         // upload buffer data for the copytriangles batch
9670                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9671                         {
9672                                 if (rsurface.batchelement3s)
9673                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9674                                 else if (rsurface.batchelement3i)
9675                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9676                         }
9677                 }
9678                 else
9679                 {
9680                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9681                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9682                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9683                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9684                 }
9685                 return;
9686         }
9687
9688         // something needs software processing, do it for real...
9689         // we only directly handle separate array data in this case and then
9690         // generate interleaved data if needed...
9691         rsurface.batchgeneratedvertex = true;
9692         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9693         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9694         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9695         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9696
9697         // now copy the vertex data into a combined array and make an index array
9698         // (this is what Quake3 does all the time)
9699         // we also apply any skeletal animation here that would have been done in
9700         // the vertex shader, because most of the dynamic vertex animation cases
9701         // need actual vertex positions and normals
9702         //if (dynamicvertex)
9703         {
9704                 rsurface.batchvertexmesh = NULL;
9705                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9706                 rsurface.batchvertexmesh_bufferoffset = 0;
9707                 rsurface.batchvertex3f = NULL;
9708                 rsurface.batchvertex3f_vertexbuffer = NULL;
9709                 rsurface.batchvertex3f_bufferoffset = 0;
9710                 rsurface.batchsvector3f = NULL;
9711                 rsurface.batchsvector3f_vertexbuffer = NULL;
9712                 rsurface.batchsvector3f_bufferoffset = 0;
9713                 rsurface.batchtvector3f = NULL;
9714                 rsurface.batchtvector3f_vertexbuffer = NULL;
9715                 rsurface.batchtvector3f_bufferoffset = 0;
9716                 rsurface.batchnormal3f = NULL;
9717                 rsurface.batchnormal3f_vertexbuffer = NULL;
9718                 rsurface.batchnormal3f_bufferoffset = 0;
9719                 rsurface.batchlightmapcolor4f = NULL;
9720                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9721                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9722                 rsurface.batchtexcoordtexture2f = NULL;
9723                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9724                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9725                 rsurface.batchtexcoordlightmap2f = NULL;
9726                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9727                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9728                 rsurface.batchskeletalindex4ub = NULL;
9729                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9730                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9731                 rsurface.batchskeletalweight4ub = NULL;
9732                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9733                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9734                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9735                 rsurface.batchelement3i_indexbuffer = NULL;
9736                 rsurface.batchelement3i_bufferoffset = 0;
9737                 rsurface.batchelement3s = NULL;
9738                 rsurface.batchelement3s_indexbuffer = NULL;
9739                 rsurface.batchelement3s_bufferoffset = 0;
9740                 rsurface.batchskeletaltransform3x4buffer = NULL;
9741                 rsurface.batchskeletaltransform3x4offset = 0;
9742                 rsurface.batchskeletaltransform3x4size = 0;
9743                 // we'll only be setting up certain arrays as needed
9744                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9745                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9746                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9747                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9748                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9749                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9750                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9751                 {
9752                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9753                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9754                 }
9755                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9756                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9757                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9758                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9759                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9760                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9761                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9762                 {
9763                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9764                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9765                 }
9766                 numvertices = 0;
9767                 numtriangles = 0;
9768                 for (i = 0;i < texturenumsurfaces;i++)
9769                 {
9770                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9771                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9772                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9773                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9774                         // copy only the data requested
9775                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9776                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9777                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9778                         {
9779                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9780                                 {
9781                                         if (rsurface.batchvertex3f)
9782                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9783                                         else
9784                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9785                                 }
9786                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9787                                 {
9788                                         if (rsurface.modelnormal3f)
9789                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9790                                         else
9791                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9792                                 }
9793                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9794                                 {
9795                                         if (rsurface.modelsvector3f)
9796                                         {
9797                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9798                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9799                                         }
9800                                         else
9801                                         {
9802                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9803                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9804                                         }
9805                                 }
9806                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9807                                 {
9808                                         if (rsurface.modellightmapcolor4f)
9809                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9810                                         else
9811                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9812                                 }
9813                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9814                                 {
9815                                         if (rsurface.modeltexcoordtexture2f)
9816                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9817                                         else
9818                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9819                                 }
9820                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9821                                 {
9822                                         if (rsurface.modeltexcoordlightmap2f)
9823                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9824                                         else
9825                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9826                                 }
9827                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9828                                 {
9829                                         if (rsurface.modelskeletalindex4ub)
9830                                         {
9831                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9832                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9833                                         }
9834                                         else
9835                                         {
9836                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9837                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9838                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9839                                                 for (j = 0;j < surfacenumvertices;j++)
9840                                                         ub[j*4] = 255;
9841                                         }
9842                                 }
9843                         }
9844                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9845                         numvertices += surfacenumvertices;
9846                         numtriangles += surfacenumtriangles;
9847                 }
9848
9849                 // generate a 16bit index array as well if possible
9850                 // (in general, dynamic batches fit)
9851                 if (numvertices <= 65536)
9852                 {
9853                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9854                         for (i = 0;i < numtriangles*3;i++)
9855                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9856                 }
9857
9858                 // since we've copied everything, the batch now starts at 0
9859                 rsurface.batchfirstvertex = 0;
9860                 rsurface.batchnumvertices = batchnumvertices;
9861                 rsurface.batchfirsttriangle = 0;
9862                 rsurface.batchnumtriangles = batchnumtriangles;
9863         }
9864
9865         // apply skeletal animation that would have been done in the vertex shader
9866         if (rsurface.batchskeletaltransform3x4)
9867         {
9868                 const unsigned char *si;
9869                 const unsigned char *sw;
9870                 const float *t[4];
9871                 const float *b = rsurface.batchskeletaltransform3x4;
9872                 float *vp, *vs, *vt, *vn;
9873                 float w[4];
9874                 float m[3][4], n[3][4];
9875                 float tp[3], ts[3], tt[3], tn[3];
9876                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9877                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9878                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9879                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9880                 si = rsurface.batchskeletalindex4ub;
9881                 sw = rsurface.batchskeletalweight4ub;
9882                 vp = rsurface.batchvertex3f;
9883                 vs = rsurface.batchsvector3f;
9884                 vt = rsurface.batchtvector3f;
9885                 vn = rsurface.batchnormal3f;
9886                 memset(m[0], 0, sizeof(m));
9887                 memset(n[0], 0, sizeof(n));
9888                 for (i = 0;i < batchnumvertices;i++)
9889                 {
9890                         t[0] = b + si[0]*12;
9891                         if (sw[0] == 255)
9892                         {
9893                                 // common case - only one matrix
9894                                 m[0][0] = t[0][ 0];
9895                                 m[0][1] = t[0][ 1];
9896                                 m[0][2] = t[0][ 2];
9897                                 m[0][3] = t[0][ 3];
9898                                 m[1][0] = t[0][ 4];
9899                                 m[1][1] = t[0][ 5];
9900                                 m[1][2] = t[0][ 6];
9901                                 m[1][3] = t[0][ 7];
9902                                 m[2][0] = t[0][ 8];
9903                                 m[2][1] = t[0][ 9];
9904                                 m[2][2] = t[0][10];
9905                                 m[2][3] = t[0][11];
9906                         }
9907                         else if (sw[2] + sw[3])
9908                         {
9909                                 // blend 4 matrices
9910                                 t[1] = b + si[1]*12;
9911                                 t[2] = b + si[2]*12;
9912                                 t[3] = b + si[3]*12;
9913                                 w[0] = sw[0] * (1.0f / 255.0f);
9914                                 w[1] = sw[1] * (1.0f / 255.0f);
9915                                 w[2] = sw[2] * (1.0f / 255.0f);
9916                                 w[3] = sw[3] * (1.0f / 255.0f);
9917                                 // blend the matrices
9918                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9919                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9920                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9921                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9922                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9923                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9924                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9925                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9926                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9927                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9928                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9929                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9930                         }
9931                         else
9932                         {
9933                                 // blend 2 matrices
9934                                 t[1] = b + si[1]*12;
9935                                 w[0] = sw[0] * (1.0f / 255.0f);
9936                                 w[1] = sw[1] * (1.0f / 255.0f);
9937                                 // blend the matrices
9938                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9939                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9940                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9941                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9942                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9943                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9944                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9945                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9946                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9947                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9948                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9949                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9950                         }
9951                         si += 4;
9952                         sw += 4;
9953                         // modify the vertex
9954                         VectorCopy(vp, tp);
9955                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9956                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9957                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9958                         vp += 3;
9959                         if (vn)
9960                         {
9961                                 // the normal transformation matrix is a set of cross products...
9962                                 CrossProduct(m[1], m[2], n[0]);
9963                                 CrossProduct(m[2], m[0], n[1]);
9964                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9965                                 VectorCopy(vn, tn);
9966                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9967                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9968                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9969                                 VectorNormalize(vn);
9970                                 vn += 3;
9971                                 if (vs)
9972                                 {
9973                                         VectorCopy(vs, ts);
9974                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9975                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9976                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9977                                         VectorNormalize(vs);
9978                                         vs += 3;
9979                                         VectorCopy(vt, tt);
9980                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9981                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9982                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9983                                         VectorNormalize(vt);
9984                                         vt += 3;
9985                                 }
9986                         }
9987                 }
9988                 rsurface.batchskeletaltransform3x4 = NULL;
9989                 rsurface.batchskeletalnumtransforms = 0;
9990         }
9991
9992         // q1bsp surfaces rendered in vertex color mode have to have colors
9993         // calculated based on lightstyles
9994         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9995         {
9996                 // generate color arrays for the surfaces in this list
9997                 int c[4];
9998                 int scale;
9999                 int size3;
10000                 const int *offsets;
10001                 const unsigned char *lm;
10002                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
10003                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10004                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10005                 numvertices = 0;
10006                 for (i = 0;i < texturenumsurfaces;i++)
10007                 {
10008                         surface = texturesurfacelist[i];
10009                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10010                         surfacenumvertices = surface->num_vertices;
10011                         if (surface->lightmapinfo->samples)
10012                         {
10013                                 for (j = 0;j < surfacenumvertices;j++)
10014                                 {
10015                                         lm = surface->lightmapinfo->samples + offsets[j];
10016                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10017                                         VectorScale(lm, scale, c);
10018                                         if (surface->lightmapinfo->styles[1] != 255)
10019                                         {
10020                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10021                                                 lm += size3;
10022                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10023                                                 VectorMA(c, scale, lm, c);
10024                                                 if (surface->lightmapinfo->styles[2] != 255)
10025                                                 {
10026                                                         lm += size3;
10027                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10028                                                         VectorMA(c, scale, lm, c);
10029                                                         if (surface->lightmapinfo->styles[3] != 255)
10030                                                         {
10031                                                                 lm += size3;
10032                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10033                                                                 VectorMA(c, scale, lm, c);
10034                                                         }
10035                                                 }
10036                                         }
10037                                         c[0] >>= 7;
10038                                         c[1] >>= 7;
10039                                         c[2] >>= 7;
10040                                         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);
10041                                         numvertices++;
10042                                 }
10043                         }
10044                         else
10045                         {
10046                                 for (j = 0;j < surfacenumvertices;j++)
10047                                 {
10048                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10049                                         numvertices++;
10050                                 }
10051                         }
10052                 }
10053         }
10054
10055         // if vertices are deformed (sprite flares and things in maps, possibly
10056         // water waves, bulges and other deformations), modify the copied vertices
10057         // in place
10058         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
10059         {
10060                 float scale;
10061                 switch (deform->deform)
10062                 {
10063                 default:
10064                 case Q3DEFORM_PROJECTIONSHADOW:
10065                 case Q3DEFORM_TEXT0:
10066                 case Q3DEFORM_TEXT1:
10067                 case Q3DEFORM_TEXT2:
10068                 case Q3DEFORM_TEXT3:
10069                 case Q3DEFORM_TEXT4:
10070                 case Q3DEFORM_TEXT5:
10071                 case Q3DEFORM_TEXT6:
10072                 case Q3DEFORM_TEXT7:
10073                 case Q3DEFORM_NONE:
10074                         break;
10075                 case Q3DEFORM_AUTOSPRITE:
10076                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10077                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10078                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10079                         VectorNormalize(newforward);
10080                         VectorNormalize(newright);
10081                         VectorNormalize(newup);
10082 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10083 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10084 //                      rsurface.batchvertex3f_bufferoffset = 0;
10085 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10086 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
10087 //                      rsurface.batchsvector3f_bufferoffset = 0;
10088 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10089 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
10090 //                      rsurface.batchtvector3f_bufferoffset = 0;
10091 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10092 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10093 //                      rsurface.batchnormal3f_bufferoffset = 0;
10094                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10095                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10096                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10097                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10098                                 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);
10099                         // a single autosprite surface can contain multiple sprites...
10100                         for (j = 0;j < batchnumvertices - 3;j += 4)
10101                         {
10102                                 VectorClear(center);
10103                                 for (i = 0;i < 4;i++)
10104                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10105                                 VectorScale(center, 0.25f, center);
10106                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10107                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10108                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10109                                 for (i = 0;i < 4;i++)
10110                                 {
10111                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10112                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10113                                 }
10114                         }
10115                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10116                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10117                         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);
10118                         break;
10119                 case Q3DEFORM_AUTOSPRITE2:
10120                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10121                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10122                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10123                         VectorNormalize(newforward);
10124                         VectorNormalize(newright);
10125                         VectorNormalize(newup);
10126 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10127 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10128 //                      rsurface.batchvertex3f_bufferoffset = 0;
10129                         {
10130                                 const float *v1, *v2;
10131                                 vec3_t start, end;
10132                                 float f, l;
10133                                 struct
10134                                 {
10135                                         float length2;
10136                                         const float *v1;
10137                                         const float *v2;
10138                                 }
10139                                 shortest[2];
10140                                 memset(shortest, 0, sizeof(shortest));
10141                                 // a single autosprite surface can contain multiple sprites...
10142                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10143                                 {
10144                                         VectorClear(center);
10145                                         for (i = 0;i < 4;i++)
10146                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10147                                         VectorScale(center, 0.25f, center);
10148                                         // find the two shortest edges, then use them to define the
10149                                         // axis vectors for rotating around the central axis
10150                                         for (i = 0;i < 6;i++)
10151                                         {
10152                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10153                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10154                                                 l = VectorDistance2(v1, v2);
10155                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10156                                                 if (v1[2] != v2[2])
10157                                                         l += (1.0f / 1024.0f);
10158                                                 if (shortest[0].length2 > l || i == 0)
10159                                                 {
10160                                                         shortest[1] = shortest[0];
10161                                                         shortest[0].length2 = l;
10162                                                         shortest[0].v1 = v1;
10163                                                         shortest[0].v2 = v2;
10164                                                 }
10165                                                 else if (shortest[1].length2 > l || i == 1)
10166                                                 {
10167                                                         shortest[1].length2 = l;
10168                                                         shortest[1].v1 = v1;
10169                                                         shortest[1].v2 = v2;
10170                                                 }
10171                                         }
10172                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10173                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10174                                         // this calculates the right vector from the shortest edge
10175                                         // and the up vector from the edge midpoints
10176                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10177                                         VectorNormalize(right);
10178                                         VectorSubtract(end, start, up);
10179                                         VectorNormalize(up);
10180                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10181                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10182                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10183                                         VectorNegate(forward, forward);
10184                                         VectorReflect(forward, 0, up, forward);
10185                                         VectorNormalize(forward);
10186                                         CrossProduct(up, forward, newright);
10187                                         VectorNormalize(newright);
10188                                         // rotate the quad around the up axis vector, this is made
10189                                         // especially easy by the fact we know the quad is flat,
10190                                         // so we only have to subtract the center position and
10191                                         // measure distance along the right vector, and then
10192                                         // multiply that by the newright vector and add back the
10193                                         // center position
10194                                         // we also need to subtract the old position to undo the
10195                                         // displacement from the center, which we do with a
10196                                         // DotProduct, the subtraction/addition of center is also
10197                                         // optimized into DotProducts here
10198                                         l = DotProduct(right, center);
10199                                         for (i = 0;i < 4;i++)
10200                                         {
10201                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10202                                                 f = DotProduct(right, v1) - l;
10203                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10204                                         }
10205                                 }
10206                         }
10207                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10208                         {
10209 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10210 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10211 //                              rsurface.batchnormal3f_bufferoffset = 0;
10212                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10213                         }
10214                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10215                         {
10216 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10217 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10218 //                              rsurface.batchsvector3f_bufferoffset = 0;
10219 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10220 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10221 //                              rsurface.batchtvector3f_bufferoffset = 0;
10222                                 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);
10223                         }
10224                         break;
10225                 case Q3DEFORM_NORMAL:
10226                         // deform the normals to make reflections wavey
10227                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10228                         rsurface.batchnormal3f_vertexbuffer = NULL;
10229                         rsurface.batchnormal3f_bufferoffset = 0;
10230                         for (j = 0;j < batchnumvertices;j++)
10231                         {
10232                                 float vertex[3];
10233                                 float *normal = rsurface.batchnormal3f + 3*j;
10234                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10235                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10236                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10237                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10238                                 VectorNormalize(normal);
10239                         }
10240                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10241                         {
10242 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10243 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10244 //                              rsurface.batchsvector3f_bufferoffset = 0;
10245 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10246 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10247 //                              rsurface.batchtvector3f_bufferoffset = 0;
10248                                 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);
10249                         }
10250                         break;
10251                 case Q3DEFORM_WAVE:
10252                         // deform vertex array to make wavey water and flags and such
10253                         waveparms[0] = deform->waveparms[0];
10254                         waveparms[1] = deform->waveparms[1];
10255                         waveparms[2] = deform->waveparms[2];
10256                         waveparms[3] = deform->waveparms[3];
10257                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10258                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10259                         // this is how a divisor of vertex influence on deformation
10260                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10261                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10262 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10263 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10264 //                      rsurface.batchvertex3f_bufferoffset = 0;
10265 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10266 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10267 //                      rsurface.batchnormal3f_bufferoffset = 0;
10268                         for (j = 0;j < batchnumvertices;j++)
10269                         {
10270                                 // if the wavefunc depends on time, evaluate it per-vertex
10271                                 if (waveparms[3])
10272                                 {
10273                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10274                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10275                                 }
10276                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10277                         }
10278                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10279                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10280                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10281                         {
10282 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10283 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10284 //                              rsurface.batchsvector3f_bufferoffset = 0;
10285 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10286 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10287 //                              rsurface.batchtvector3f_bufferoffset = 0;
10288                                 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);
10289                         }
10290                         break;
10291                 case Q3DEFORM_BULGE:
10292                         // deform vertex array to make the surface have moving bulges
10293 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10294 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10295 //                      rsurface.batchvertex3f_bufferoffset = 0;
10296 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10297 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10298 //                      rsurface.batchnormal3f_bufferoffset = 0;
10299                         for (j = 0;j < batchnumvertices;j++)
10300                         {
10301                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10302                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10303                         }
10304                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10305                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10306                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10307                         {
10308 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10309 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10310 //                              rsurface.batchsvector3f_bufferoffset = 0;
10311 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10312 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10313 //                              rsurface.batchtvector3f_bufferoffset = 0;
10314                                 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);
10315                         }
10316                         break;
10317                 case Q3DEFORM_MOVE:
10318                         // deform vertex array
10319                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10320                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10321                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10322                         VectorScale(deform->parms, scale, waveparms);
10323 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10324 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10325 //                      rsurface.batchvertex3f_bufferoffset = 0;
10326                         for (j = 0;j < batchnumvertices;j++)
10327                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10328                         break;
10329                 }
10330         }
10331
10332         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10333         {
10334         // generate texcoords based on the chosen texcoord source
10335                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10336                 {
10337                 default:
10338                 case Q3TCGEN_TEXTURE:
10339                         break;
10340                 case Q3TCGEN_LIGHTMAP:
10341         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10342         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10343         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10344                         if (rsurface.batchtexcoordlightmap2f)
10345                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10346                         break;
10347                 case Q3TCGEN_VECTOR:
10348         //              rsurface.batchtexcoordtexture2f = 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                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10354                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10355                         }
10356                         break;
10357                 case Q3TCGEN_ENVIRONMENT:
10358                         // make environment reflections using a spheremap
10359                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10360                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10361                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10362                         for (j = 0;j < batchnumvertices;j++)
10363                         {
10364                                 // identical to Q3A's method, but executed in worldspace so
10365                                 // carried models can be shiny too
10366
10367                                 float viewer[3], d, reflected[3], worldreflected[3];
10368
10369                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10370                                 // VectorNormalize(viewer);
10371
10372                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10373
10374                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10375                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10376                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10377                                 // note: this is proportinal to viewer, so we can normalize later
10378
10379                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10380                                 VectorNormalize(worldreflected);
10381
10382                                 // note: this sphere map only uses world x and z!
10383                                 // so positive and negative y will LOOK THE SAME.
10384                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10385                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10386                         }
10387                         break;
10388                 }
10389                 // the only tcmod that needs software vertex processing is turbulent, so
10390                 // check for it here and apply the changes if needed
10391                 // and we only support that as the first one
10392                 // (handling a mixture of turbulent and other tcmods would be problematic
10393                 //  without punting it entirely to a software path)
10394                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10395                 {
10396                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10397                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10398         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10399         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10400         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10401                         for (j = 0;j < batchnumvertices;j++)
10402                         {
10403                                 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);
10404                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10405                         }
10406                 }
10407         }
10408
10409         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10410         {
10411                 // convert the modified arrays to vertex structs
10412 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10413 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10414 //              rsurface.batchvertexmesh_bufferoffset = 0;
10415                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10416                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10417                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10418                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10419                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10420                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10421                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10422                 {
10423                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10424                         {
10425                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10426                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10427                         }
10428                 }
10429                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10430                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10431                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10432                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10433                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10434                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10435                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10436                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10437                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10438                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10439                 {
10440                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10441                         {
10442                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10443                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10444                         }
10445                 }
10446         }
10447
10448         // upload buffer data for the dynamic batch
10449         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10450         {
10451                 if (rsurface.batchvertexmesh)
10452                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10453                 else
10454                 {
10455                         if (rsurface.batchvertex3f)
10456                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10457                         if (rsurface.batchsvector3f)
10458                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10459                         if (rsurface.batchtvector3f)
10460                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10461                         if (rsurface.batchnormal3f)
10462                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10463                         if (rsurface.batchlightmapcolor4f)
10464                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10465                         if (rsurface.batchtexcoordtexture2f)
10466                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10467                         if (rsurface.batchtexcoordlightmap2f)
10468                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10469                         if (rsurface.batchskeletalindex4ub)
10470                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10471                         if (rsurface.batchskeletalweight4ub)
10472                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10473                 }
10474                 if (rsurface.batchelement3s)
10475                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10476                 else if (rsurface.batchelement3i)
10477                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10478         }
10479 }
10480
10481 void RSurf_DrawBatch(void)
10482 {
10483         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10484         // through the pipeline, killing it earlier in the pipeline would have
10485         // per-surface overhead rather than per-batch overhead, so it's best to
10486         // reject it here, before it hits glDraw.
10487         if (rsurface.batchnumtriangles == 0)
10488                 return;
10489 #if 0
10490         // batch debugging code
10491         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10492         {
10493                 int i;
10494                 int j;
10495                 int c;
10496                 const int *e;
10497                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10498                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10499                 {
10500                         c = e[i];
10501                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10502                         {
10503                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10504                                 {
10505                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10506                                                 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);
10507                                         break;
10508                                 }
10509                         }
10510                 }
10511         }
10512 #endif
10513         if (rsurface.batchmultidraw)
10514         {
10515                 // issue multiple draws rather than copying index data
10516                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10517                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10518                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10519                 for (i = 0;i < numsurfaces;)
10520                 {
10521                         // combine consecutive surfaces as one draw
10522                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10523                                 if (surfacelist[j] != surfacelist[k] + 1)
10524                                         break;
10525                         firstvertex = surfacelist[i]->num_firstvertex;
10526                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10527                         firsttriangle = surfacelist[i]->num_firsttriangle;
10528                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10529                         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);
10530                         i = j;
10531                 }
10532         }
10533         else
10534         {
10535                 // there is only one consecutive run of index data (may have been combined)
10536                 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);
10537         }
10538 }
10539
10540 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10541 {
10542         // pick the closest matching water plane
10543         int planeindex, vertexindex, bestplaneindex = -1;
10544         float d, bestd;
10545         vec3_t vert;
10546         const float *v;
10547         r_waterstate_waterplane_t *p;
10548         qboolean prepared = false;
10549         bestd = 0;
10550         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10551         {
10552                 if(p->camera_entity != rsurface.texture->camera_entity)
10553                         continue;
10554                 d = 0;
10555                 if(!prepared)
10556                 {
10557                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10558                         prepared = true;
10559                         if(rsurface.batchnumvertices == 0)
10560                                 break;
10561                 }
10562                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10563                 {
10564                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10565                         d += fabs(PlaneDiff(vert, &p->plane));
10566                 }
10567                 if (bestd > d || bestplaneindex < 0)
10568                 {
10569                         bestd = d;
10570                         bestplaneindex = planeindex;
10571                 }
10572         }
10573         return bestplaneindex;
10574         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10575         // this situation though, as it might be better to render single larger
10576         // batches with useless stuff (backface culled for example) than to
10577         // render multiple smaller batches
10578 }
10579
10580 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10581 {
10582         int i;
10583         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10584         rsurface.passcolor4f_vertexbuffer = 0;
10585         rsurface.passcolor4f_bufferoffset = 0;
10586         for (i = 0;i < rsurface.batchnumvertices;i++)
10587                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10588 }
10589
10590 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10591 {
10592         int i;
10593         float f;
10594         const float *v;
10595         const float *c;
10596         float *c2;
10597         if (rsurface.passcolor4f)
10598         {
10599                 // generate color arrays
10600                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10601                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10602                 rsurface.passcolor4f_vertexbuffer = 0;
10603                 rsurface.passcolor4f_bufferoffset = 0;
10604                 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)
10605                 {
10606                         f = RSurf_FogVertex(v);
10607                         c2[0] = c[0] * f;
10608                         c2[1] = c[1] * f;
10609                         c2[2] = c[2] * f;
10610                         c2[3] = c[3];
10611                 }
10612         }
10613         else
10614         {
10615                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10616                 rsurface.passcolor4f_vertexbuffer = 0;
10617                 rsurface.passcolor4f_bufferoffset = 0;
10618                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10619                 {
10620                         f = RSurf_FogVertex(v);
10621                         c2[0] = f;
10622                         c2[1] = f;
10623                         c2[2] = f;
10624                         c2[3] = 1;
10625                 }
10626         }
10627 }
10628
10629 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10630 {
10631         int i;
10632         float f;
10633         const float *v;
10634         const float *c;
10635         float *c2;
10636         if (!rsurface.passcolor4f)
10637                 return;
10638         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10639         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10640         rsurface.passcolor4f_vertexbuffer = 0;
10641         rsurface.passcolor4f_bufferoffset = 0;
10642         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)
10643         {
10644                 f = RSurf_FogVertex(v);
10645                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10646                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10647                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10648                 c2[3] = c[3];
10649         }
10650 }
10651
10652 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10653 {
10654         int i;
10655         const float *c;
10656         float *c2;
10657         if (!rsurface.passcolor4f)
10658                 return;
10659         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10660         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10661         rsurface.passcolor4f_vertexbuffer = 0;
10662         rsurface.passcolor4f_bufferoffset = 0;
10663         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10664         {
10665                 c2[0] = c[0] * r;
10666                 c2[1] = c[1] * g;
10667                 c2[2] = c[2] * b;
10668                 c2[3] = c[3] * a;
10669         }
10670 }
10671
10672 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10673 {
10674         int i;
10675         const float *c;
10676         float *c2;
10677         if (!rsurface.passcolor4f)
10678                 return;
10679         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10680         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10681         rsurface.passcolor4f_vertexbuffer = 0;
10682         rsurface.passcolor4f_bufferoffset = 0;
10683         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10684         {
10685                 c2[0] = c[0] + r_refdef.scene.ambient;
10686                 c2[1] = c[1] + r_refdef.scene.ambient;
10687                 c2[2] = c[2] + r_refdef.scene.ambient;
10688                 c2[3] = c[3];
10689         }
10690 }
10691
10692 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10693 {
10694         // TODO: optimize
10695         rsurface.passcolor4f = NULL;
10696         rsurface.passcolor4f_vertexbuffer = 0;
10697         rsurface.passcolor4f_bufferoffset = 0;
10698         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10699         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10700         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10701         GL_Color(r, g, b, a);
10702         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10703         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10704         R_Mesh_TexMatrix(0, NULL);
10705         RSurf_DrawBatch();
10706 }
10707
10708 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10709 {
10710         // TODO: optimize applyfog && applycolor case
10711         // just apply fog if necessary, and tint the fog color array if necessary
10712         rsurface.passcolor4f = NULL;
10713         rsurface.passcolor4f_vertexbuffer = 0;
10714         rsurface.passcolor4f_bufferoffset = 0;
10715         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10716         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10717         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10718         GL_Color(r, g, b, a);
10719         RSurf_DrawBatch();
10720 }
10721
10722 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10723 {
10724         // TODO: optimize
10725         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10726         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10727         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10728         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10729         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10730         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10731         GL_Color(r, g, b, a);
10732         RSurf_DrawBatch();
10733 }
10734
10735 static void RSurf_DrawBatch_GL11_ClampColor(void)
10736 {
10737         int i;
10738         const float *c1;
10739         float *c2;
10740         if (!rsurface.passcolor4f)
10741                 return;
10742         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10743         {
10744                 c2[0] = bound(0.0f, c1[0], 1.0f);
10745                 c2[1] = bound(0.0f, c1[1], 1.0f);
10746                 c2[2] = bound(0.0f, c1[2], 1.0f);
10747                 c2[3] = bound(0.0f, c1[3], 1.0f);
10748         }
10749 }
10750
10751 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10752 {
10753         int i;
10754         float f;
10755         const float *v;
10756         const float *n;
10757         float *c;
10758         //vec3_t eyedir;
10759
10760         // fake shading
10761         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10762         rsurface.passcolor4f_vertexbuffer = 0;
10763         rsurface.passcolor4f_bufferoffset = 0;
10764         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)
10765         {
10766                 f = -DotProduct(r_refdef.view.forward, n);
10767                 f = max(0, f);
10768                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10769                 f *= r_refdef.lightmapintensity;
10770                 Vector4Set(c, f, f, f, 1);
10771         }
10772 }
10773
10774 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10775 {
10776         RSurf_DrawBatch_GL11_ApplyFakeLight();
10777         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10778         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10779         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10780         GL_Color(r, g, b, a);
10781         RSurf_DrawBatch();
10782 }
10783
10784 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10785 {
10786         int i;
10787         float f;
10788         float alpha;
10789         const float *v;
10790         const float *n;
10791         float *c;
10792         vec3_t ambientcolor;
10793         vec3_t diffusecolor;
10794         vec3_t lightdir;
10795         // TODO: optimize
10796         // model lighting
10797         VectorCopy(rsurface.modellight_lightdir, lightdir);
10798         f = 0.5f * r_refdef.lightmapintensity;
10799         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10800         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10801         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10802         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10803         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10804         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10805         alpha = *a;
10806         if (VectorLength2(diffusecolor) > 0)
10807         {
10808                 // q3-style directional shading
10809                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10810                 rsurface.passcolor4f_vertexbuffer = 0;
10811                 rsurface.passcolor4f_bufferoffset = 0;
10812                 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)
10813                 {
10814                         if ((f = DotProduct(n, lightdir)) > 0)
10815                                 VectorMA(ambientcolor, f, diffusecolor, c);
10816                         else
10817                                 VectorCopy(ambientcolor, c);
10818                         c[3] = alpha;
10819                 }
10820                 *r = 1;
10821                 *g = 1;
10822                 *b = 1;
10823                 *a = 1;
10824                 *applycolor = false;
10825         }
10826         else
10827         {
10828                 *r = ambientcolor[0];
10829                 *g = ambientcolor[1];
10830                 *b = ambientcolor[2];
10831                 rsurface.passcolor4f = NULL;
10832                 rsurface.passcolor4f_vertexbuffer = 0;
10833                 rsurface.passcolor4f_bufferoffset = 0;
10834         }
10835 }
10836
10837 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10838 {
10839         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10840         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10841         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10842         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10843         GL_Color(r, g, b, a);
10844         RSurf_DrawBatch();
10845 }
10846
10847 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10848 {
10849         int i;
10850         float f;
10851         const float *v;
10852         float *c;
10853
10854         // fake shading
10855         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10856         rsurface.passcolor4f_vertexbuffer = 0;
10857         rsurface.passcolor4f_bufferoffset = 0;
10858
10859         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10860         {
10861                 f = 1 - RSurf_FogVertex(v);
10862                 c[0] = r;
10863                 c[1] = g;
10864                 c[2] = b;
10865                 c[3] = f * a;
10866         }
10867 }
10868
10869 void RSurf_SetupDepthAndCulling(void)
10870 {
10871         // submodels are biased to avoid z-fighting with world surfaces that they
10872         // may be exactly overlapping (avoids z-fighting artifacts on certain
10873         // doors and things in Quake maps)
10874         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10875         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10876         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10877         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10878 }
10879
10880 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10881 {
10882         // transparent sky would be ridiculous
10883         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10884                 return;
10885         R_SetupShader_Generic_NoTexture(false, false);
10886         skyrenderlater = true;
10887         RSurf_SetupDepthAndCulling();
10888         GL_DepthMask(true);
10889         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10890         // skymasking on them, and Quake3 never did sky masking (unlike
10891         // software Quake and software Quake2), so disable the sky masking
10892         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10893         // and skymasking also looks very bad when noclipping outside the
10894         // level, so don't use it then either.
10895         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10896         {
10897                 R_Mesh_ResetTextureState();
10898                 if (skyrendermasked)
10899                 {
10900                         R_SetupShader_DepthOrShadow(false, false, false);
10901                         // depth-only (masking)
10902                         GL_ColorMask(0,0,0,0);
10903                         // just to make sure that braindead drivers don't draw
10904                         // anything despite that colormask...
10905                         GL_BlendFunc(GL_ZERO, GL_ONE);
10906                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10907                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10908                 }
10909                 else
10910                 {
10911                         R_SetupShader_Generic_NoTexture(false, false);
10912                         // fog sky
10913                         GL_BlendFunc(GL_ONE, GL_ZERO);
10914                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10915                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10916                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10917                 }
10918                 RSurf_DrawBatch();
10919                 if (skyrendermasked)
10920                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10921         }
10922         R_Mesh_ResetTextureState();
10923         GL_Color(1, 1, 1, 1);
10924 }
10925
10926 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10927 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10928 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10929 {
10930         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10931                 return;
10932         if (prepass)
10933         {
10934                 // render screenspace normalmap to texture
10935                 GL_DepthMask(true);
10936                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10937                 RSurf_DrawBatch();
10938                 return;
10939         }
10940
10941         // bind lightmap texture
10942
10943         // water/refraction/reflection/camera surfaces have to be handled specially
10944         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10945         {
10946                 int start, end, startplaneindex;
10947                 for (start = 0;start < texturenumsurfaces;start = end)
10948                 {
10949                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10950                         if(startplaneindex < 0)
10951                         {
10952                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10953                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10954                                 end = start + 1;
10955                                 continue;
10956                         }
10957                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10958                                 ;
10959                         // now that we have a batch using the same planeindex, render it
10960                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10961                         {
10962                                 // render water or distortion background
10963                                 GL_DepthMask(true);
10964                                 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);
10965                                 RSurf_DrawBatch();
10966                                 // blend surface on top
10967                                 GL_DepthMask(false);
10968                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10969                                 RSurf_DrawBatch();
10970                         }
10971                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10972                         {
10973                                 // render surface with reflection texture as input
10974                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10975                                 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);
10976                                 RSurf_DrawBatch();
10977                         }
10978                 }
10979                 return;
10980         }
10981
10982         // render surface batch normally
10983         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10984         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);
10985         RSurf_DrawBatch();
10986 }
10987
10988 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10989 {
10990         // OpenGL 1.3 path - anything not completely ancient
10991         qboolean applycolor;
10992         qboolean applyfog;
10993         int layerindex;
10994         const texturelayer_t *layer;
10995         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);
10996         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10997
10998         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10999         {
11000                 vec4_t layercolor;
11001                 int layertexrgbscale;
11002                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11003                 {
11004                         if (layerindex == 0)
11005                                 GL_AlphaTest(true);
11006                         else
11007                         {
11008                                 GL_AlphaTest(false);
11009                                 GL_DepthFunc(GL_EQUAL);
11010                         }
11011                 }
11012                 GL_DepthMask(layer->depthmask && writedepth);
11013                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11014                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11015                 {
11016                         layertexrgbscale = 4;
11017                         VectorScale(layer->color, 0.25f, layercolor);
11018                 }
11019                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11020                 {
11021                         layertexrgbscale = 2;
11022                         VectorScale(layer->color, 0.5f, layercolor);
11023                 }
11024                 else
11025                 {
11026                         layertexrgbscale = 1;
11027                         VectorScale(layer->color, 1.0f, layercolor);
11028                 }
11029                 layercolor[3] = layer->color[3];
11030                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11031                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11032                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11033                 switch (layer->type)
11034                 {
11035                 case TEXTURELAYERTYPE_LITTEXTURE:
11036                         // single-pass lightmapped texture with 2x rgbscale
11037                         R_Mesh_TexBind(0, r_texture_white);
11038                         R_Mesh_TexMatrix(0, NULL);
11039                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11040                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11041                         R_Mesh_TexBind(1, layer->texture);
11042                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11043                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11044                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11045                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11046                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11047                         else if (FAKELIGHT_ENABLED)
11048                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11049                         else if (rsurface.uselightmaptexture)
11050                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11051                         else
11052                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11053                         break;
11054                 case TEXTURELAYERTYPE_TEXTURE:
11055                         // singletexture unlit texture with transparency support
11056                         R_Mesh_TexBind(0, layer->texture);
11057                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11058                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11059                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11060                         R_Mesh_TexBind(1, 0);
11061                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11062                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11063                         break;
11064                 case TEXTURELAYERTYPE_FOG:
11065                         // singletexture fogging
11066                         if (layer->texture)
11067                         {
11068                                 R_Mesh_TexBind(0, layer->texture);
11069                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11070                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11071                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11072                         }
11073                         else
11074                         {
11075                                 R_Mesh_TexBind(0, 0);
11076                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11077                         }
11078                         R_Mesh_TexBind(1, 0);
11079                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11080                         // generate a color array for the fog pass
11081                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11082                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11083                         RSurf_DrawBatch();
11084                         break;
11085                 default:
11086                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11087                 }
11088         }
11089         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11090         {
11091                 GL_DepthFunc(GL_LEQUAL);
11092                 GL_AlphaTest(false);
11093         }
11094 }
11095
11096 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11097 {
11098         // OpenGL 1.1 - crusty old voodoo path
11099         qboolean applyfog;
11100         int layerindex;
11101         const texturelayer_t *layer;
11102         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);
11103         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11104
11105         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11106         {
11107                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11108                 {
11109                         if (layerindex == 0)
11110                                 GL_AlphaTest(true);
11111                         else
11112                         {
11113                                 GL_AlphaTest(false);
11114                                 GL_DepthFunc(GL_EQUAL);
11115                         }
11116                 }
11117                 GL_DepthMask(layer->depthmask && writedepth);
11118                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11119                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11120                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11121                 switch (layer->type)
11122                 {
11123                 case TEXTURELAYERTYPE_LITTEXTURE:
11124                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11125                         {
11126                                 // two-pass lit texture with 2x rgbscale
11127                                 // first the lightmap pass
11128                                 R_Mesh_TexBind(0, r_texture_white);
11129                                 R_Mesh_TexMatrix(0, NULL);
11130                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11131                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11132                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11133                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11134                                 else if (FAKELIGHT_ENABLED)
11135                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11136                                 else if (rsurface.uselightmaptexture)
11137                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11138                                 else
11139                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11140                                 // then apply the texture to it
11141                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11142                                 R_Mesh_TexBind(0, layer->texture);
11143                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11144                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11145                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11146                                 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);
11147                         }
11148                         else
11149                         {
11150                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11151                                 R_Mesh_TexBind(0, layer->texture);
11152                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11153                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11154                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11155                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11156                                         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);
11157                                 else if (FAKELIGHT_ENABLED)
11158                                         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);
11159                                 else
11160                                         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);
11161                         }
11162                         break;
11163                 case TEXTURELAYERTYPE_TEXTURE:
11164                         // singletexture unlit texture with transparency support
11165                         R_Mesh_TexBind(0, layer->texture);
11166                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11167                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11168                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11169                         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);
11170                         break;
11171                 case TEXTURELAYERTYPE_FOG:
11172                         // singletexture fogging
11173                         if (layer->texture)
11174                         {
11175                                 R_Mesh_TexBind(0, layer->texture);
11176                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11177                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11178                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11179                         }
11180                         else
11181                         {
11182                                 R_Mesh_TexBind(0, 0);
11183                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11184                         }
11185                         // generate a color array for the fog pass
11186                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11187                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11188                         RSurf_DrawBatch();
11189                         break;
11190                 default:
11191                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11192                 }
11193         }
11194         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11195         {
11196                 GL_DepthFunc(GL_LEQUAL);
11197                 GL_AlphaTest(false);
11198         }
11199 }
11200
11201 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11202 {
11203         int vi;
11204         int j;
11205         r_vertexgeneric_t *batchvertex;
11206         float c[4];
11207
11208 //      R_Mesh_ResetTextureState();
11209         R_SetupShader_Generic_NoTexture(false, false);
11210
11211         if(rsurface.texture && rsurface.texture->currentskinframe)
11212         {
11213                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11214                 c[3] *= rsurface.texture->currentalpha;
11215         }
11216         else
11217         {
11218                 c[0] = 1;
11219                 c[1] = 0;
11220                 c[2] = 1;
11221                 c[3] = 1;
11222         }
11223
11224         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11225         {
11226                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11227                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11228                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11229         }
11230
11231         // brighten it up (as texture value 127 means "unlit")
11232         c[0] *= 2 * r_refdef.view.colorscale;
11233         c[1] *= 2 * r_refdef.view.colorscale;
11234         c[2] *= 2 * r_refdef.view.colorscale;
11235
11236         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11237                 c[3] *= r_wateralpha.value;
11238
11239         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11240         {
11241                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11242                 GL_DepthMask(false);
11243         }
11244         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11245         {
11246                 GL_BlendFunc(GL_ONE, GL_ONE);
11247                 GL_DepthMask(false);
11248         }
11249         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11250         {
11251                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11252                 GL_DepthMask(false);
11253         }
11254         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11255         {
11256                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11257                 GL_DepthMask(false);
11258         }
11259         else
11260         {
11261                 GL_BlendFunc(GL_ONE, GL_ZERO);
11262                 GL_DepthMask(writedepth);
11263         }
11264
11265         if (r_showsurfaces.integer == 3)
11266         {
11267                 rsurface.passcolor4f = NULL;
11268
11269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11270                 {
11271                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11272
11273                         rsurface.passcolor4f = NULL;
11274                         rsurface.passcolor4f_vertexbuffer = 0;
11275                         rsurface.passcolor4f_bufferoffset = 0;
11276                 }
11277                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11278                 {
11279                         qboolean applycolor = true;
11280                         float one = 1.0;
11281
11282                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11283
11284                         r_refdef.lightmapintensity = 1;
11285                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11286                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11287                 }
11288                 else if (FAKELIGHT_ENABLED)
11289                 {
11290                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11291
11292                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11293                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11294                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11295                 }
11296                 else
11297                 {
11298                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11299
11300                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11301                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11302                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11303                 }
11304
11305                 if(!rsurface.passcolor4f)
11306                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11307
11308                 RSurf_DrawBatch_GL11_ApplyAmbient();
11309                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11310                 if(r_refdef.fogenabled)
11311                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11312                 RSurf_DrawBatch_GL11_ClampColor();
11313
11314                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11315                 R_SetupShader_Generic_NoTexture(false, false);
11316                 RSurf_DrawBatch();
11317         }
11318         else if (!r_refdef.view.showdebug)
11319         {
11320                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11321                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11322                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11323                 {
11324                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11325                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11326                 }
11327                 R_Mesh_PrepareVertices_Generic_Unlock();
11328                 RSurf_DrawBatch();
11329         }
11330         else if (r_showsurfaces.integer == 4)
11331         {
11332                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11333                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11334                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11335                 {
11336                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11337                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11338                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11339                 }
11340                 R_Mesh_PrepareVertices_Generic_Unlock();
11341                 RSurf_DrawBatch();
11342         }
11343         else if (r_showsurfaces.integer == 2)
11344         {
11345                 const int *e;
11346                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11347                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11348                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11349                 {
11350                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11351                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11352                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11353                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11354                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11355                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11356                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11357                 }
11358                 R_Mesh_PrepareVertices_Generic_Unlock();
11359                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11360         }
11361         else
11362         {
11363                 int texturesurfaceindex;
11364                 int k;
11365                 const msurface_t *surface;
11366                 float surfacecolor4f[4];
11367                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11368                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11369                 vi = 0;
11370                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11371                 {
11372                         surface = texturesurfacelist[texturesurfaceindex];
11373                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11374                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11375                         for (j = 0;j < surface->num_vertices;j++)
11376                         {
11377                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11378                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11379                                 vi++;
11380                         }
11381                 }
11382                 R_Mesh_PrepareVertices_Generic_Unlock();
11383                 RSurf_DrawBatch();
11384         }
11385 }
11386
11387 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11388 {
11389         CHECKGLERROR
11390         RSurf_SetupDepthAndCulling();
11391         if (r_showsurfaces.integer)
11392         {
11393                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11394                 return;
11395         }
11396         switch (vid.renderpath)
11397         {
11398         case RENDERPATH_GL20:
11399         case RENDERPATH_D3D9:
11400         case RENDERPATH_D3D10:
11401         case RENDERPATH_D3D11:
11402         case RENDERPATH_SOFT:
11403         case RENDERPATH_GLES2:
11404                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11405                 break;
11406         case RENDERPATH_GL13:
11407         case RENDERPATH_GLES1:
11408                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11409                 break;
11410         case RENDERPATH_GL11:
11411                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11412                 break;
11413         }
11414         CHECKGLERROR
11415 }
11416
11417 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11418 {
11419         CHECKGLERROR
11420         RSurf_SetupDepthAndCulling();
11421         if (r_showsurfaces.integer)
11422         {
11423                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11424                 return;
11425         }
11426         switch (vid.renderpath)
11427         {
11428         case RENDERPATH_GL20:
11429         case RENDERPATH_D3D9:
11430         case RENDERPATH_D3D10:
11431         case RENDERPATH_D3D11:
11432         case RENDERPATH_SOFT:
11433         case RENDERPATH_GLES2:
11434                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11435                 break;
11436         case RENDERPATH_GL13:
11437         case RENDERPATH_GLES1:
11438                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11439                 break;
11440         case RENDERPATH_GL11:
11441                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11442                 break;
11443         }
11444         CHECKGLERROR
11445 }
11446
11447 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11448 {
11449         int i, j;
11450         int texturenumsurfaces, endsurface;
11451         texture_t *texture;
11452         const msurface_t *surface;
11453         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11454
11455         // if the model is static it doesn't matter what value we give for
11456         // wantnormals and wanttangents, so this logic uses only rules applicable
11457         // to a model, knowing that they are meaningless otherwise
11458         if (ent == r_refdef.scene.worldentity)
11459                 RSurf_ActiveWorldEntity();
11460         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11461                 RSurf_ActiveModelEntity(ent, false, false, false);
11462         else
11463         {
11464                 switch (vid.renderpath)
11465                 {
11466                 case RENDERPATH_GL20:
11467                 case RENDERPATH_D3D9:
11468                 case RENDERPATH_D3D10:
11469                 case RENDERPATH_D3D11:
11470                 case RENDERPATH_SOFT:
11471                 case RENDERPATH_GLES2:
11472                         RSurf_ActiveModelEntity(ent, true, true, false);
11473                         break;
11474                 case RENDERPATH_GL11:
11475                 case RENDERPATH_GL13:
11476                 case RENDERPATH_GLES1:
11477                         RSurf_ActiveModelEntity(ent, true, false, false);
11478                         break;
11479                 }
11480         }
11481
11482         if (r_transparentdepthmasking.integer)
11483         {
11484                 qboolean setup = false;
11485                 for (i = 0;i < numsurfaces;i = j)
11486                 {
11487                         j = i + 1;
11488                         surface = rsurface.modelsurfaces + surfacelist[i];
11489                         texture = surface->texture;
11490                         rsurface.texture = R_GetCurrentTexture(texture);
11491                         rsurface.lightmaptexture = NULL;
11492                         rsurface.deluxemaptexture = NULL;
11493                         rsurface.uselightmaptexture = false;
11494                         // scan ahead until we find a different texture
11495                         endsurface = min(i + 1024, numsurfaces);
11496                         texturenumsurfaces = 0;
11497                         texturesurfacelist[texturenumsurfaces++] = surface;
11498                         for (;j < endsurface;j++)
11499                         {
11500                                 surface = rsurface.modelsurfaces + surfacelist[j];
11501                                 if (texture != surface->texture)
11502                                         break;
11503                                 texturesurfacelist[texturenumsurfaces++] = surface;
11504                         }
11505                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11506                                 continue;
11507                         // render the range of surfaces as depth
11508                         if (!setup)
11509                         {
11510                                 setup = true;
11511                                 GL_ColorMask(0,0,0,0);
11512                                 GL_Color(1,1,1,1);
11513                                 GL_DepthTest(true);
11514                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11515                                 GL_DepthMask(true);
11516 //                              R_Mesh_ResetTextureState();
11517                         }
11518                         RSurf_SetupDepthAndCulling();
11519                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11520                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11521                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11522                         RSurf_DrawBatch();
11523                 }
11524                 if (setup)
11525                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11526         }
11527
11528         for (i = 0;i < numsurfaces;i = j)
11529         {
11530                 j = i + 1;
11531                 surface = rsurface.modelsurfaces + surfacelist[i];
11532                 texture = surface->texture;
11533                 rsurface.texture = R_GetCurrentTexture(texture);
11534                 // scan ahead until we find a different texture
11535                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11536                 texturenumsurfaces = 0;
11537                 texturesurfacelist[texturenumsurfaces++] = surface;
11538                 if(FAKELIGHT_ENABLED)
11539                 {
11540                         rsurface.lightmaptexture = NULL;
11541                         rsurface.deluxemaptexture = NULL;
11542                         rsurface.uselightmaptexture = false;
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                 }
11551                 else
11552                 {
11553                         rsurface.lightmaptexture = surface->lightmaptexture;
11554                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11555                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11556                         for (;j < endsurface;j++)
11557                         {
11558                                 surface = rsurface.modelsurfaces + surfacelist[j];
11559                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11560                                         break;
11561                                 texturesurfacelist[texturenumsurfaces++] = surface;
11562                         }
11563                 }
11564                 // render the range of surfaces
11565                 if (ent == r_refdef.scene.worldentity)
11566                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11567                 else
11568                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11569         }
11570         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11571 }
11572
11573 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11574 {
11575         // transparent surfaces get pushed off into the transparent queue
11576         int surfacelistindex;
11577         const msurface_t *surface;
11578         vec3_t tempcenter, center;
11579         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11580         {
11581                 surface = texturesurfacelist[surfacelistindex];
11582                 if (r_transparent_sortsurfacesbynearest.integer)
11583                 {
11584                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11585                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11586                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11587                 }
11588                 else
11589                 {
11590                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11591                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11592                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11593                 }
11594                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11595                 if (rsurface.entity->transparent_offset) // transparent offset
11596                 {
11597                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11598                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11599                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11600                 }
11601                 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);
11602         }
11603 }
11604
11605 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11606 {
11607         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11608                 return;
11609         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11610                 return;
11611         RSurf_SetupDepthAndCulling();
11612         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11613         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11614         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11615         RSurf_DrawBatch();
11616 }
11617
11618 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11619 {
11620         CHECKGLERROR
11621         if (depthonly)
11622                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11623         else if (prepass)
11624         {
11625                 if (!rsurface.texture->currentnumlayers)
11626                         return;
11627                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11628                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11629                 else
11630                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11631         }
11632         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11633                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11634         else if (!rsurface.texture->currentnumlayers)
11635                 return;
11636         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11637         {
11638                 // in the deferred case, transparent surfaces were queued during prepass
11639                 if (!r_shadow_usingdeferredprepass)
11640                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11641         }
11642         else
11643         {
11644                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11645                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11646         }
11647         CHECKGLERROR
11648 }
11649
11650 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11651 {
11652         int i, j;
11653         texture_t *texture;
11654         R_FrameData_SetMark();
11655         // break the surface list down into batches by texture and use of lightmapping
11656         for (i = 0;i < numsurfaces;i = j)
11657         {
11658                 j = i + 1;
11659                 // texture is the base texture pointer, rsurface.texture is the
11660                 // current frame/skin the texture is directing us to use (for example
11661                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11662                 // use skin 1 instead)
11663                 texture = surfacelist[i]->texture;
11664                 rsurface.texture = R_GetCurrentTexture(texture);
11665                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11666                 {
11667                         // if this texture is not the kind we want, skip ahead to the next one
11668                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11669                                 ;
11670                         continue;
11671                 }
11672                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11673                 {
11674                         rsurface.lightmaptexture = NULL;
11675                         rsurface.deluxemaptexture = NULL;
11676                         rsurface.uselightmaptexture = false;
11677                         // simply scan ahead until we find a different texture or lightmap state
11678                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11679                                 ;
11680                 }
11681                 else
11682                 {
11683                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11684                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11685                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11686                         // simply scan ahead until we find a different texture or lightmap state
11687                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11688                                 ;
11689                 }
11690                 // render the range of surfaces
11691                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11692         }
11693         R_FrameData_ReturnToMark();
11694 }
11695
11696 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11697 {
11698         CHECKGLERROR
11699         if (depthonly)
11700                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11701         else if (prepass)
11702         {
11703                 if (!rsurface.texture->currentnumlayers)
11704                         return;
11705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11706                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11707                 else
11708                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11709         }
11710         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11711                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11712         else if (!rsurface.texture->currentnumlayers)
11713                 return;
11714         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11715         {
11716                 // in the deferred case, transparent surfaces were queued during prepass
11717                 if (!r_shadow_usingdeferredprepass)
11718                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11719         }
11720         else
11721         {
11722                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11723                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11724         }
11725         CHECKGLERROR
11726 }
11727
11728 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11729 {
11730         int i, j;
11731         texture_t *texture;
11732         R_FrameData_SetMark();
11733         // break the surface list down into batches by texture and use of lightmapping
11734         for (i = 0;i < numsurfaces;i = j)
11735         {
11736                 j = i + 1;
11737                 // texture is the base texture pointer, rsurface.texture is the
11738                 // current frame/skin the texture is directing us to use (for example
11739                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11740                 // use skin 1 instead)
11741                 texture = surfacelist[i]->texture;
11742                 rsurface.texture = R_GetCurrentTexture(texture);
11743                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11744                 {
11745                         // if this texture is not the kind we want, skip ahead to the next one
11746                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11747                                 ;
11748                         continue;
11749                 }
11750                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11751                 {
11752                         rsurface.lightmaptexture = NULL;
11753                         rsurface.deluxemaptexture = NULL;
11754                         rsurface.uselightmaptexture = false;
11755                         // simply scan ahead until we find a different texture or lightmap state
11756                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11757                                 ;
11758                 }
11759                 else
11760                 {
11761                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11762                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11763                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11764                         // simply scan ahead until we find a different texture or lightmap state
11765                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11766                                 ;
11767                 }
11768                 // render the range of surfaces
11769                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11770         }
11771         R_FrameData_ReturnToMark();
11772 }
11773
11774 float locboxvertex3f[6*4*3] =
11775 {
11776         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11777         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11778         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11779         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11780         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11781         1,0,0, 0,0,0, 0,1,0, 1,1,0
11782 };
11783
11784 unsigned short locboxelements[6*2*3] =
11785 {
11786          0, 1, 2, 0, 2, 3,
11787          4, 5, 6, 4, 6, 7,
11788          8, 9,10, 8,10,11,
11789         12,13,14, 12,14,15,
11790         16,17,18, 16,18,19,
11791         20,21,22, 20,22,23
11792 };
11793
11794 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11795 {
11796         int i, j;
11797         cl_locnode_t *loc = (cl_locnode_t *)ent;
11798         vec3_t mins, size;
11799         float vertex3f[6*4*3];
11800         CHECKGLERROR
11801         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11802         GL_DepthMask(false);
11803         GL_DepthRange(0, 1);
11804         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11805         GL_DepthTest(true);
11806         GL_CullFace(GL_NONE);
11807         R_EntityMatrix(&identitymatrix);
11808
11809 //      R_Mesh_ResetTextureState();
11810
11811         i = surfacelist[0];
11812         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11813                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11814                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11815                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11816
11817         if (VectorCompare(loc->mins, loc->maxs))
11818         {
11819                 VectorSet(size, 2, 2, 2);
11820                 VectorMA(loc->mins, -0.5f, size, mins);
11821         }
11822         else
11823         {
11824                 VectorCopy(loc->mins, mins);
11825                 VectorSubtract(loc->maxs, loc->mins, size);
11826         }
11827
11828         for (i = 0;i < 6*4*3;)
11829                 for (j = 0;j < 3;j++, i++)
11830                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11831
11832         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11833         R_SetupShader_Generic_NoTexture(false, false);
11834         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11835 }
11836
11837 void R_DrawLocs(void)
11838 {
11839         int index;
11840         cl_locnode_t *loc, *nearestloc;
11841         vec3_t center;
11842         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11843         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11844         {
11845                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11846                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11847         }
11848 }
11849
11850 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11851 {
11852         if (decalsystem->decals)
11853                 Mem_Free(decalsystem->decals);
11854         memset(decalsystem, 0, sizeof(*decalsystem));
11855 }
11856
11857 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)
11858 {
11859         tridecal_t *decal;
11860         tridecal_t *decals;
11861         int i;
11862
11863         // expand or initialize the system
11864         if (decalsystem->maxdecals <= decalsystem->numdecals)
11865         {
11866                 decalsystem_t old = *decalsystem;
11867                 qboolean useshortelements;
11868                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11869                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11870                 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)));
11871                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11872                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11873                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11874                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11875                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11876                 if (decalsystem->numdecals)
11877                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11878                 if (old.decals)
11879                         Mem_Free(old.decals);
11880                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11881                         decalsystem->element3i[i] = i;
11882                 if (useshortelements)
11883                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11884                                 decalsystem->element3s[i] = i;
11885         }
11886
11887         // grab a decal and search for another free slot for the next one
11888         decals = decalsystem->decals;
11889         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11890         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11891                 ;
11892         decalsystem->freedecal = i;
11893         if (decalsystem->numdecals <= i)
11894                 decalsystem->numdecals = i + 1;
11895
11896         // initialize the decal
11897         decal->lived = 0;
11898         decal->triangleindex = triangleindex;
11899         decal->surfaceindex = surfaceindex;
11900         decal->decalsequence = decalsequence;
11901         decal->color4f[0][0] = c0[0];
11902         decal->color4f[0][1] = c0[1];
11903         decal->color4f[0][2] = c0[2];
11904         decal->color4f[0][3] = 1;
11905         decal->color4f[1][0] = c1[0];
11906         decal->color4f[1][1] = c1[1];
11907         decal->color4f[1][2] = c1[2];
11908         decal->color4f[1][3] = 1;
11909         decal->color4f[2][0] = c2[0];
11910         decal->color4f[2][1] = c2[1];
11911         decal->color4f[2][2] = c2[2];
11912         decal->color4f[2][3] = 1;
11913         decal->vertex3f[0][0] = v0[0];
11914         decal->vertex3f[0][1] = v0[1];
11915         decal->vertex3f[0][2] = v0[2];
11916         decal->vertex3f[1][0] = v1[0];
11917         decal->vertex3f[1][1] = v1[1];
11918         decal->vertex3f[1][2] = v1[2];
11919         decal->vertex3f[2][0] = v2[0];
11920         decal->vertex3f[2][1] = v2[1];
11921         decal->vertex3f[2][2] = v2[2];
11922         decal->texcoord2f[0][0] = t0[0];
11923         decal->texcoord2f[0][1] = t0[1];
11924         decal->texcoord2f[1][0] = t1[0];
11925         decal->texcoord2f[1][1] = t1[1];
11926         decal->texcoord2f[2][0] = t2[0];
11927         decal->texcoord2f[2][1] = t2[1];
11928         TriangleNormal(v0, v1, v2, decal->plane);
11929         VectorNormalize(decal->plane);
11930         decal->plane[3] = DotProduct(v0, decal->plane);
11931 }
11932
11933 extern cvar_t cl_decals_bias;
11934 extern cvar_t cl_decals_models;
11935 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11936 // baseparms, parms, temps
11937 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)
11938 {
11939         int cornerindex;
11940         int index;
11941         float v[9][3];
11942         const float *vertex3f;
11943         const float *normal3f;
11944         int numpoints;
11945         float points[2][9][3];
11946         float temp[3];
11947         float tc[9][2];
11948         float f;
11949         float c[9][4];
11950         const int *e;
11951
11952         e = rsurface.modelelement3i + 3*triangleindex;
11953
11954         vertex3f = rsurface.modelvertex3f;
11955         normal3f = rsurface.modelnormal3f;
11956
11957         if (normal3f)
11958         {
11959                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11960                 {
11961                         index = 3*e[cornerindex];
11962                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11963                 }
11964         }
11965         else
11966         {
11967                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11968                 {
11969                         index = 3*e[cornerindex];
11970                         VectorCopy(vertex3f + index, v[cornerindex]);
11971                 }
11972         }
11973
11974         // cull backfaces
11975         //TriangleNormal(v[0], v[1], v[2], normal);
11976         //if (DotProduct(normal, localnormal) < 0.0f)
11977         //      continue;
11978         // clip by each of the box planes formed from the projection matrix
11979         // if anything survives, we emit the decal
11980         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]);
11981         if (numpoints < 3)
11982                 return;
11983         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]);
11984         if (numpoints < 3)
11985                 return;
11986         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]);
11987         if (numpoints < 3)
11988                 return;
11989         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]);
11990         if (numpoints < 3)
11991                 return;
11992         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]);
11993         if (numpoints < 3)
11994                 return;
11995         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]);
11996         if (numpoints < 3)
11997                 return;
11998         // some part of the triangle survived, so we have to accept it...
11999         if (dynamic)
12000         {
12001                 // dynamic always uses the original triangle
12002                 numpoints = 3;
12003                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12004                 {
12005                         index = 3*e[cornerindex];
12006                         VectorCopy(vertex3f + index, v[cornerindex]);
12007                 }
12008         }
12009         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12010         {
12011                 // convert vertex positions to texcoords
12012                 Matrix4x4_Transform(projection, v[cornerindex], temp);
12013                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12014                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12015                 // calculate distance fade from the projection origin
12016                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12017                 f = bound(0.0f, f, 1.0f);
12018                 c[cornerindex][0] = r * f;
12019                 c[cornerindex][1] = g * f;
12020                 c[cornerindex][2] = b * f;
12021                 c[cornerindex][3] = 1.0f;
12022                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12023         }
12024         if (dynamic)
12025                 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);
12026         else
12027                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12028                         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);
12029 }
12030 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)
12031 {
12032         matrix4x4_t projection;
12033         decalsystem_t *decalsystem;
12034         qboolean dynamic;
12035         dp_model_t *model;
12036         const msurface_t *surface;
12037         const msurface_t *surfaces;
12038         const int *surfacelist;
12039         const texture_t *texture;
12040         int numtriangles;
12041         int numsurfacelist;
12042         int surfacelistindex;
12043         int surfaceindex;
12044         int triangleindex;
12045         float localorigin[3];
12046         float localnormal[3];
12047         float localmins[3];
12048         float localmaxs[3];
12049         float localsize;
12050         //float normal[3];
12051         float planes[6][4];
12052         float angles[3];
12053         bih_t *bih;
12054         int bih_triangles_count;
12055         int bih_triangles[256];
12056         int bih_surfaces[256];
12057
12058         decalsystem = &ent->decalsystem;
12059         model = ent->model;
12060         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12061         {
12062                 R_DecalSystem_Reset(&ent->decalsystem);
12063                 return;
12064         }
12065
12066         if (!model->brush.data_leafs && !cl_decals_models.integer)
12067         {
12068                 if (decalsystem->model)
12069                         R_DecalSystem_Reset(decalsystem);
12070                 return;
12071         }
12072
12073         if (decalsystem->model != model)
12074                 R_DecalSystem_Reset(decalsystem);
12075         decalsystem->model = model;
12076
12077         RSurf_ActiveModelEntity(ent, true, false, false);
12078
12079         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12080         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12081         VectorNormalize(localnormal);
12082         localsize = worldsize*rsurface.inversematrixscale;
12083         localmins[0] = localorigin[0] - localsize;
12084         localmins[1] = localorigin[1] - localsize;
12085         localmins[2] = localorigin[2] - localsize;
12086         localmaxs[0] = localorigin[0] + localsize;
12087         localmaxs[1] = localorigin[1] + localsize;
12088         localmaxs[2] = localorigin[2] + localsize;
12089
12090         //VectorCopy(localnormal, planes[4]);
12091         //VectorVectors(planes[4], planes[2], planes[0]);
12092         AnglesFromVectors(angles, localnormal, NULL, false);
12093         AngleVectors(angles, planes[0], planes[2], planes[4]);
12094         VectorNegate(planes[0], planes[1]);
12095         VectorNegate(planes[2], planes[3]);
12096         VectorNegate(planes[4], planes[5]);
12097         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12098         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12099         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12100         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12101         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12102         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12103
12104 #if 1
12105 // works
12106 {
12107         matrix4x4_t forwardprojection;
12108         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12109         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12110 }
12111 #else
12112 // broken
12113 {
12114         float projectionvector[4][3];
12115         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12116         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12117         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12118         projectionvector[0][0] = planes[0][0] * ilocalsize;
12119         projectionvector[0][1] = planes[1][0] * ilocalsize;
12120         projectionvector[0][2] = planes[2][0] * ilocalsize;
12121         projectionvector[1][0] = planes[0][1] * ilocalsize;
12122         projectionvector[1][1] = planes[1][1] * ilocalsize;
12123         projectionvector[1][2] = planes[2][1] * ilocalsize;
12124         projectionvector[2][0] = planes[0][2] * ilocalsize;
12125         projectionvector[2][1] = planes[1][2] * ilocalsize;
12126         projectionvector[2][2] = planes[2][2] * ilocalsize;
12127         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12128         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12129         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12130         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12131 }
12132 #endif
12133
12134         dynamic = model->surfmesh.isanimated;
12135         numsurfacelist = model->nummodelsurfaces;
12136         surfacelist = model->sortedmodelsurfaces;
12137         surfaces = model->data_surfaces;
12138
12139         bih = NULL;
12140         bih_triangles_count = -1;
12141         if(!dynamic)
12142         {
12143                 if(model->render_bih.numleafs)
12144                         bih = &model->render_bih;
12145                 else if(model->collision_bih.numleafs)
12146                         bih = &model->collision_bih;
12147         }
12148         if(bih)
12149                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12150         if(bih_triangles_count == 0)
12151                 return;
12152         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12153                 return;
12154         if(bih_triangles_count > 0)
12155         {
12156                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12157                 {
12158                         surfaceindex = bih_surfaces[triangleindex];
12159                         surface = surfaces + surfaceindex;
12160                         texture = surface->texture;
12161                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12162                                 continue;
12163                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12164                                 continue;
12165                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12166                 }
12167         }
12168         else
12169         {
12170                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12171                 {
12172                         surfaceindex = surfacelist[surfacelistindex];
12173                         surface = surfaces + surfaceindex;
12174                         // check cull box first because it rejects more than any other check
12175                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12176                                 continue;
12177                         // skip transparent surfaces
12178                         texture = surface->texture;
12179                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12180                                 continue;
12181                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12182                                 continue;
12183                         numtriangles = surface->num_triangles;
12184                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12185                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12186                 }
12187         }
12188 }
12189
12190 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12191 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)
12192 {
12193         int renderentityindex;
12194         float worldmins[3];
12195         float worldmaxs[3];
12196         entity_render_t *ent;
12197
12198         if (!cl_decals_newsystem.integer)
12199                 return;
12200
12201         worldmins[0] = worldorigin[0] - worldsize;
12202         worldmins[1] = worldorigin[1] - worldsize;
12203         worldmins[2] = worldorigin[2] - worldsize;
12204         worldmaxs[0] = worldorigin[0] + worldsize;
12205         worldmaxs[1] = worldorigin[1] + worldsize;
12206         worldmaxs[2] = worldorigin[2] + worldsize;
12207
12208         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12209
12210         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12211         {
12212                 ent = r_refdef.scene.entities[renderentityindex];
12213                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12214                         continue;
12215
12216                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12217         }
12218 }
12219
12220 typedef struct r_decalsystem_splatqueue_s
12221 {
12222         vec3_t worldorigin;
12223         vec3_t worldnormal;
12224         float color[4];
12225         float tcrange[4];
12226         float worldsize;
12227         unsigned int decalsequence;
12228 }
12229 r_decalsystem_splatqueue_t;
12230
12231 int r_decalsystem_numqueued = 0;
12232 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12233
12234 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)
12235 {
12236         r_decalsystem_splatqueue_t *queue;
12237
12238         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12239                 return;
12240
12241         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12242         VectorCopy(worldorigin, queue->worldorigin);
12243         VectorCopy(worldnormal, queue->worldnormal);
12244         Vector4Set(queue->color, r, g, b, a);
12245         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12246         queue->worldsize = worldsize;
12247         queue->decalsequence = cl.decalsequence++;
12248 }
12249
12250 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12251 {
12252         int i;
12253         r_decalsystem_splatqueue_t *queue;
12254
12255         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12256                 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);
12257         r_decalsystem_numqueued = 0;
12258 }
12259
12260 extern cvar_t cl_decals_max;
12261 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12262 {
12263         int i;
12264         decalsystem_t *decalsystem = &ent->decalsystem;
12265         int numdecals;
12266         unsigned int killsequence;
12267         tridecal_t *decal;
12268         float frametime;
12269         float lifetime;
12270
12271         if (!decalsystem->numdecals)
12272                 return;
12273
12274         if (r_showsurfaces.integer)
12275                 return;
12276
12277         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12278         {
12279                 R_DecalSystem_Reset(decalsystem);
12280                 return;
12281         }
12282
12283         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12284         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12285
12286         if (decalsystem->lastupdatetime)
12287                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12288         else
12289                 frametime = 0;
12290         decalsystem->lastupdatetime = r_refdef.scene.time;
12291         numdecals = decalsystem->numdecals;
12292
12293         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12294         {
12295                 if (decal->color4f[0][3])
12296                 {
12297                         decal->lived += frametime;
12298                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12299                         {
12300                                 memset(decal, 0, sizeof(*decal));
12301                                 if (decalsystem->freedecal > i)
12302                                         decalsystem->freedecal = i;
12303                         }
12304                 }
12305         }
12306         decal = decalsystem->decals;
12307         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12308                 numdecals--;
12309
12310         // collapse the array by shuffling the tail decals into the gaps
12311         for (;;)
12312         {
12313                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12314                         decalsystem->freedecal++;
12315                 if (decalsystem->freedecal == numdecals)
12316                         break;
12317                 decal[decalsystem->freedecal] = decal[--numdecals];
12318         }
12319
12320         decalsystem->numdecals = numdecals;
12321
12322         if (numdecals <= 0)
12323         {
12324                 // if there are no decals left, reset decalsystem
12325                 R_DecalSystem_Reset(decalsystem);
12326         }
12327 }
12328
12329 extern skinframe_t *decalskinframe;
12330 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12331 {
12332         int i;
12333         decalsystem_t *decalsystem = &ent->decalsystem;
12334         int numdecals;
12335         tridecal_t *decal;
12336         float faderate;
12337         float alpha;
12338         float *v3f;
12339         float *c4f;
12340         float *t2f;
12341         const int *e;
12342         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12343         int numtris = 0;
12344
12345         numdecals = decalsystem->numdecals;
12346         if (!numdecals)
12347                 return;
12348
12349         if (r_showsurfaces.integer)
12350                 return;
12351
12352         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12353         {
12354                 R_DecalSystem_Reset(decalsystem);
12355                 return;
12356         }
12357
12358         // if the model is static it doesn't matter what value we give for
12359         // wantnormals and wanttangents, so this logic uses only rules applicable
12360         // to a model, knowing that they are meaningless otherwise
12361         if (ent == r_refdef.scene.worldentity)
12362                 RSurf_ActiveWorldEntity();
12363         else
12364                 RSurf_ActiveModelEntity(ent, false, false, false);
12365
12366         decalsystem->lastupdatetime = r_refdef.scene.time;
12367
12368         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12369
12370         // update vertex positions for animated models
12371         v3f = decalsystem->vertex3f;
12372         c4f = decalsystem->color4f;
12373         t2f = decalsystem->texcoord2f;
12374         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12375         {
12376                 if (!decal->color4f[0][3])
12377                         continue;
12378
12379                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12380                         continue;
12381
12382                 // skip backfaces
12383                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12384                         continue;
12385
12386                 // update color values for fading decals
12387                 if (decal->lived >= cl_decals_time.value)
12388                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12389                 else
12390                         alpha = 1.0f;
12391
12392                 c4f[ 0] = decal->color4f[0][0] * alpha;
12393                 c4f[ 1] = decal->color4f[0][1] * alpha;
12394                 c4f[ 2] = decal->color4f[0][2] * alpha;
12395                 c4f[ 3] = 1;
12396                 c4f[ 4] = decal->color4f[1][0] * alpha;
12397                 c4f[ 5] = decal->color4f[1][1] * alpha;
12398                 c4f[ 6] = decal->color4f[1][2] * alpha;
12399                 c4f[ 7] = 1;
12400                 c4f[ 8] = decal->color4f[2][0] * alpha;
12401                 c4f[ 9] = decal->color4f[2][1] * alpha;
12402                 c4f[10] = decal->color4f[2][2] * alpha;
12403                 c4f[11] = 1;
12404
12405                 t2f[0] = decal->texcoord2f[0][0];
12406                 t2f[1] = decal->texcoord2f[0][1];
12407                 t2f[2] = decal->texcoord2f[1][0];
12408                 t2f[3] = decal->texcoord2f[1][1];
12409                 t2f[4] = decal->texcoord2f[2][0];
12410                 t2f[5] = decal->texcoord2f[2][1];
12411
12412                 // update vertex positions for animated models
12413                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12414                 {
12415                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12416                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12417                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12418                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12419                 }
12420                 else
12421                 {
12422                         VectorCopy(decal->vertex3f[0], v3f);
12423                         VectorCopy(decal->vertex3f[1], v3f + 3);
12424                         VectorCopy(decal->vertex3f[2], v3f + 6);
12425                 }
12426
12427                 if (r_refdef.fogenabled)
12428                 {
12429                         alpha = RSurf_FogVertex(v3f);
12430                         VectorScale(c4f, alpha, c4f);
12431                         alpha = RSurf_FogVertex(v3f + 3);
12432                         VectorScale(c4f + 4, alpha, c4f + 4);
12433                         alpha = RSurf_FogVertex(v3f + 6);
12434                         VectorScale(c4f + 8, alpha, c4f + 8);
12435                 }
12436
12437                 v3f += 9;
12438                 c4f += 12;
12439                 t2f += 6;
12440                 numtris++;
12441         }
12442
12443         if (numtris > 0)
12444         {
12445                 r_refdef.stats[r_stat_drawndecals] += numtris;
12446
12447                 // now render the decals all at once
12448                 // (this assumes they all use one particle font texture!)
12449                 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);
12450 //              R_Mesh_ResetTextureState();
12451                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12452                 GL_DepthMask(false);
12453                 GL_DepthRange(0, 1);
12454                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12455                 GL_DepthTest(true);
12456                 GL_CullFace(GL_NONE);
12457                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12458                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12459                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12460         }
12461 }
12462
12463 static void R_DrawModelDecals(void)
12464 {
12465         int i, numdecals;
12466
12467         // fade faster when there are too many decals
12468         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12469         for (i = 0;i < r_refdef.scene.numentities;i++)
12470                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12471
12472         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12473         for (i = 0;i < r_refdef.scene.numentities;i++)
12474                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12475                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12476
12477         R_DecalSystem_ApplySplatEntitiesQueue();
12478
12479         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12480         for (i = 0;i < r_refdef.scene.numentities;i++)
12481                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12482
12483         r_refdef.stats[r_stat_totaldecals] += numdecals;
12484
12485         if (r_showsurfaces.integer)
12486                 return;
12487
12488         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12489
12490         for (i = 0;i < r_refdef.scene.numentities;i++)
12491         {
12492                 if (!r_refdef.viewcache.entityvisible[i])
12493                         continue;
12494                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12495                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12496         }
12497 }
12498
12499 extern cvar_t mod_collision_bih;
12500 static void R_DrawDebugModel(void)
12501 {
12502         entity_render_t *ent = rsurface.entity;
12503         int i, j, flagsmask;
12504         const msurface_t *surface;
12505         dp_model_t *model = ent->model;
12506
12507         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12508                 return;
12509
12510         if (r_showoverdraw.value > 0)
12511         {
12512                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12513                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12514                 R_SetupShader_Generic_NoTexture(false, false);
12515                 GL_DepthTest(false);
12516                 GL_DepthMask(false);
12517                 GL_DepthRange(0, 1);
12518                 GL_BlendFunc(GL_ONE, GL_ONE);
12519                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12520                 {
12521                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12522                                 continue;
12523                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12524                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12525                         {
12526                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12527                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12528                                 if (!rsurface.texture->currentlayers->depthmask)
12529                                         GL_Color(c, 0, 0, 1.0f);
12530                                 else if (ent == r_refdef.scene.worldentity)
12531                                         GL_Color(c, c, c, 1.0f);
12532                                 else
12533                                         GL_Color(0, c, 0, 1.0f);
12534                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12535                                 RSurf_DrawBatch();
12536                         }
12537                 }
12538                 rsurface.texture = NULL;
12539         }
12540
12541         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12542
12543 //      R_Mesh_ResetTextureState();
12544         R_SetupShader_Generic_NoTexture(false, false);
12545         GL_DepthRange(0, 1);
12546         GL_DepthTest(!r_showdisabledepthtest.integer);
12547         GL_DepthMask(false);
12548         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12549
12550         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12551         {
12552                 int triangleindex;
12553                 int bihleafindex;
12554                 qboolean cullbox = false;
12555                 const q3mbrush_t *brush;
12556                 const bih_t *bih = &model->collision_bih;
12557                 const bih_leaf_t *bihleaf;
12558                 float vertex3f[3][3];
12559                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12560                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12561                 {
12562                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12563                                 continue;
12564                         switch (bihleaf->type)
12565                         {
12566                         case BIH_BRUSH:
12567                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12568                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12569                                 {
12570                                         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);
12571                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12572                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12573                                 }
12574                                 break;
12575                         case BIH_COLLISIONTRIANGLE:
12576                                 triangleindex = bihleaf->itemindex;
12577                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12578                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12579                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12580                                 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);
12581                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12582                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12583                                 break;
12584                         case BIH_RENDERTRIANGLE:
12585                                 triangleindex = bihleaf->itemindex;
12586                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12587                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12588                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12589                                 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);
12590                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12591                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12592                                 break;
12593                         }
12594                 }
12595         }
12596
12597         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12598
12599 #ifndef USE_GLES2
12600         if (r_showtris.integer && qglPolygonMode)
12601         {
12602                 if (r_showdisabledepthtest.integer)
12603                 {
12604                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12605                         GL_DepthMask(false);
12606                 }
12607                 else
12608                 {
12609                         GL_BlendFunc(GL_ONE, GL_ZERO);
12610                         GL_DepthMask(true);
12611                 }
12612                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12613                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12614                 {
12615                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12616                                 continue;
12617                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12618                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12619                         {
12620                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12621                                 if (!rsurface.texture->currentlayers->depthmask)
12622                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12623                                 else if (ent == r_refdef.scene.worldentity)
12624                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12625                                 else
12626                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12627                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12628                                 RSurf_DrawBatch();
12629                         }
12630                 }
12631                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12632                 rsurface.texture = NULL;
12633         }
12634
12635         if (r_shownormals.value != 0 && qglBegin)
12636         {
12637                 int l, k;
12638                 vec3_t v;
12639                 if (r_showdisabledepthtest.integer)
12640                 {
12641                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12642                         GL_DepthMask(false);
12643                 }
12644                 else
12645                 {
12646                         GL_BlendFunc(GL_ONE, GL_ZERO);
12647                         GL_DepthMask(true);
12648                 }
12649                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12650                 {
12651                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12652                                 continue;
12653                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12654                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12655                         {
12656                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12657                                 qglBegin(GL_LINES);
12658                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12659                                 {
12660                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12661                                         {
12662                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12663                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12664                                                 qglVertex3f(v[0], v[1], v[2]);
12665                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12666                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12667                                                 qglVertex3f(v[0], v[1], v[2]);
12668                                         }
12669                                 }
12670                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12671                                 {
12672                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12673                                         {
12674                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12675                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12676                                                 qglVertex3f(v[0], v[1], v[2]);
12677                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12678                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12679                                                 qglVertex3f(v[0], v[1], v[2]);
12680                                         }
12681                                 }
12682                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12683                                 {
12684                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12685                                         {
12686                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12687                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12688                                                 qglVertex3f(v[0], v[1], v[2]);
12689                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12690                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12691                                                 qglVertex3f(v[0], v[1], v[2]);
12692                                         }
12693                                 }
12694                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12695                                 {
12696                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12697                                         {
12698                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12699                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12700                                                 qglVertex3f(v[0], v[1], v[2]);
12701                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12702                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12703                                                 qglVertex3f(v[0], v[1], v[2]);
12704                                         }
12705                                 }
12706                                 qglEnd();
12707                                 CHECKGLERROR
12708                         }
12709                 }
12710                 rsurface.texture = NULL;
12711         }
12712 #endif
12713 }
12714
12715 int r_maxsurfacelist = 0;
12716 const msurface_t **r_surfacelist = NULL;
12717 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12718 {
12719         int i, j, endj, flagsmask;
12720         dp_model_t *model = r_refdef.scene.worldmodel;
12721         msurface_t *surfaces;
12722         unsigned char *update;
12723         int numsurfacelist = 0;
12724         if (model == NULL)
12725                 return;
12726
12727         if (r_maxsurfacelist < model->num_surfaces)
12728         {
12729                 r_maxsurfacelist = model->num_surfaces;
12730                 if (r_surfacelist)
12731                         Mem_Free((msurface_t**)r_surfacelist);
12732                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12733         }
12734
12735         RSurf_ActiveWorldEntity();
12736
12737         surfaces = model->data_surfaces;
12738         update = model->brushq1.lightmapupdateflags;
12739
12740         // update light styles on this submodel
12741         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12742         {
12743                 model_brush_lightstyleinfo_t *style;
12744                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12745                 {
12746                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12747                         {
12748                                 int *list = style->surfacelist;
12749                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12750                                 for (j = 0;j < style->numsurfaces;j++)
12751                                         update[list[j]] = true;
12752                         }
12753                 }
12754         }
12755
12756         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12757
12758         if (debug)
12759         {
12760                 R_DrawDebugModel();
12761                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12762                 return;
12763         }
12764
12765         rsurface.lightmaptexture = NULL;
12766         rsurface.deluxemaptexture = NULL;
12767         rsurface.uselightmaptexture = false;
12768         rsurface.texture = NULL;
12769         rsurface.rtlight = NULL;
12770         numsurfacelist = 0;
12771         // add visible surfaces to draw list
12772         for (i = 0;i < model->nummodelsurfaces;i++)
12773         {
12774                 j = model->sortedmodelsurfaces[i];
12775                 if (r_refdef.viewcache.world_surfacevisible[j])
12776                         r_surfacelist[numsurfacelist++] = surfaces + j;
12777         }
12778         // update lightmaps if needed
12779         if (model->brushq1.firstrender)
12780         {
12781                 model->brushq1.firstrender = false;
12782                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12783                         if (update[j])
12784                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12785         }
12786         else if (update)
12787         {
12788                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12789                         if (r_refdef.viewcache.world_surfacevisible[j])
12790                                 if (update[j])
12791                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12792         }
12793         // don't do anything if there were no surfaces
12794         if (!numsurfacelist)
12795         {
12796                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12797                 return;
12798         }
12799         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12800
12801         // add to stats if desired
12802         if (r_speeds.integer && !skysurfaces && !depthonly)
12803         {
12804                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12805                 for (j = 0;j < numsurfacelist;j++)
12806                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12807         }
12808
12809         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12810 }
12811
12812 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12813 {
12814         int i, j, endj, flagsmask;
12815         dp_model_t *model = ent->model;
12816         msurface_t *surfaces;
12817         unsigned char *update;
12818         int numsurfacelist = 0;
12819         if (model == NULL)
12820                 return;
12821
12822         if (r_maxsurfacelist < model->num_surfaces)
12823         {
12824                 r_maxsurfacelist = model->num_surfaces;
12825                 if (r_surfacelist)
12826                         Mem_Free((msurface_t **)r_surfacelist);
12827                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12828         }
12829
12830         // if the model is static it doesn't matter what value we give for
12831         // wantnormals and wanttangents, so this logic uses only rules applicable
12832         // to a model, knowing that they are meaningless otherwise
12833         if (ent == r_refdef.scene.worldentity)
12834                 RSurf_ActiveWorldEntity();
12835         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12836                 RSurf_ActiveModelEntity(ent, false, false, false);
12837         else if (prepass)
12838                 RSurf_ActiveModelEntity(ent, true, true, true);
12839         else if (depthonly)
12840         {
12841                 switch (vid.renderpath)
12842                 {
12843                 case RENDERPATH_GL20:
12844                 case RENDERPATH_D3D9:
12845                 case RENDERPATH_D3D10:
12846                 case RENDERPATH_D3D11:
12847                 case RENDERPATH_SOFT:
12848                 case RENDERPATH_GLES2:
12849                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12850                         break;
12851                 case RENDERPATH_GL11:
12852                 case RENDERPATH_GL13:
12853                 case RENDERPATH_GLES1:
12854                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12855                         break;
12856                 }
12857         }
12858         else
12859         {
12860                 switch (vid.renderpath)
12861                 {
12862                 case RENDERPATH_GL20:
12863                 case RENDERPATH_D3D9:
12864                 case RENDERPATH_D3D10:
12865                 case RENDERPATH_D3D11:
12866                 case RENDERPATH_SOFT:
12867                 case RENDERPATH_GLES2:
12868                         RSurf_ActiveModelEntity(ent, true, true, false);
12869                         break;
12870                 case RENDERPATH_GL11:
12871                 case RENDERPATH_GL13:
12872                 case RENDERPATH_GLES1:
12873                         RSurf_ActiveModelEntity(ent, true, false, false);
12874                         break;
12875                 }
12876         }
12877
12878         surfaces = model->data_surfaces;
12879         update = model->brushq1.lightmapupdateflags;
12880
12881         // update light styles
12882         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12883         {
12884                 model_brush_lightstyleinfo_t *style;
12885                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12886                 {
12887                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12888                         {
12889                                 int *list = style->surfacelist;
12890                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12891                                 for (j = 0;j < style->numsurfaces;j++)
12892                                         update[list[j]] = true;
12893                         }
12894                 }
12895         }
12896
12897         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12898
12899         if (debug)
12900         {
12901                 R_DrawDebugModel();
12902                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12903                 return;
12904         }
12905
12906         rsurface.lightmaptexture = NULL;
12907         rsurface.deluxemaptexture = NULL;
12908         rsurface.uselightmaptexture = false;
12909         rsurface.texture = NULL;
12910         rsurface.rtlight = NULL;
12911         numsurfacelist = 0;
12912         // add visible surfaces to draw list
12913         for (i = 0;i < model->nummodelsurfaces;i++)
12914                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12915         // don't do anything if there were no surfaces
12916         if (!numsurfacelist)
12917         {
12918                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12919                 return;
12920         }
12921         // update lightmaps if needed
12922         if (update)
12923         {
12924                 int updated = 0;
12925                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12926                 {
12927                         if (update[j])
12928                         {
12929                                 updated++;
12930                                 R_BuildLightMap(ent, surfaces + j);
12931                         }
12932                 }
12933         }
12934
12935         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12936
12937         // add to stats if desired
12938         if (r_speeds.integer && !skysurfaces && !depthonly)
12939         {
12940                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12941                 for (j = 0;j < numsurfacelist;j++)
12942                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12943         }
12944
12945         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12946 }
12947
12948 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12949 {
12950         static texture_t texture;
12951         static msurface_t surface;
12952         const msurface_t *surfacelist = &surface;
12953
12954         // fake enough texture and surface state to render this geometry
12955
12956         texture.update_lastrenderframe = -1; // regenerate this texture
12957         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12958         texture.basealpha = 1.0f;
12959         texture.currentskinframe = skinframe;
12960         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12961         texture.offsetmapping = OFFSETMAPPING_OFF;
12962         texture.offsetscale = 1;
12963         texture.specularscalemod = 1;
12964         texture.specularpowermod = 1;
12965         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12966         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12967         // JUST GREP FOR "specularscalemod = 1".
12968
12969         surface.texture = &texture;
12970         surface.num_triangles = numtriangles;
12971         surface.num_firsttriangle = firsttriangle;
12972         surface.num_vertices = numvertices;
12973         surface.num_firstvertex = firstvertex;
12974
12975         // now render it
12976         rsurface.texture = R_GetCurrentTexture(surface.texture);
12977         rsurface.lightmaptexture = NULL;
12978         rsurface.deluxemaptexture = NULL;
12979         rsurface.uselightmaptexture = false;
12980         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12981 }
12982
12983 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)
12984 {
12985         static msurface_t surface;
12986         const msurface_t *surfacelist = &surface;
12987
12988         // fake enough texture and surface state to render this geometry
12989         surface.texture = texture;
12990         surface.num_triangles = numtriangles;
12991         surface.num_firsttriangle = firsttriangle;
12992         surface.num_vertices = numvertices;
12993         surface.num_firstvertex = firstvertex;
12994
12995         // now render it
12996         rsurface.texture = R_GetCurrentTexture(surface.texture);
12997         rsurface.lightmaptexture = NULL;
12998         rsurface.deluxemaptexture = NULL;
12999         rsurface.uselightmaptexture = false;
13000         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13001 }