]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Fix some viewport issues with r_viewfbo and r_bloom by passing view size information...
[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 "r_shadow.h"
24 #include "polygon.h"
25 #include "image.h"
26 #include "ft2.h"
27 #include "csprogs.h"
28 #include "cl_video.h"
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
83
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
97 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
104 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
105 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
115 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
122
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
126
127 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
131 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
132
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
144 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
147 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
158 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
159
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
168
169 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
170 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
171
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
175
176 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
177 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
178 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
179 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
180 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
181 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
182 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
183 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
184 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
185
186 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
187 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
188 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
189 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
190 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
192 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
193 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
194 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
195 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
196 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
197 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
198 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
199 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
200 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
201 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
202 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
203 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
204 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
205
206 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
207 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
208 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
209 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
210 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
211 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
212 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
213 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
214 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
215 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
216
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
221
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
224
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
231
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
242
243 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
244
245 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
246
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
248
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
250
251 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
252 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
255
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
258
259 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
260
261 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
263 {
264         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
268 };
269
270 extern cvar_t v_glslgamma_2d;
271
272 extern qboolean v_flipped_state;
273
274 r_framebufferstate_t r_fb;
275
276 /// shadow volume bsp struct with automatically growing nodes buffer
277 svbsp_t r_svbsp;
278
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
280
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
294
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
297 {
298         char basename[64];
299         rtexture_t *texture;
300 }
301 cubemapinfo_t;
302
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
305
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
309
310 typedef struct r_qwskincache_s
311 {
312         char name[MAX_QPATH];
313         skinframe_t *skinframe;
314 }
315 r_qwskincache_t;
316
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
319
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 extern const float r_d3dscreenvertex3f[12];
323 const float r_screenvertex3f[12] =
324 {
325         0, 0, 0,
326         1, 0, 0,
327         1, 1, 0,
328         0, 1, 0
329 };
330 const float r_d3dscreenvertex3f[12] =
331 {
332         0, 1, 0,
333         1, 1, 0,
334         1, 0, 0,
335         0, 0, 0
336 };
337
338 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
339 {
340         int i;
341         for (i = 0;i < verts;i++)
342         {
343                 out[0] = in[0] * r;
344                 out[1] = in[1] * g;
345                 out[2] = in[2] * b;
346                 out[3] = in[3];
347                 in += 4;
348                 out += 4;
349         }
350 }
351
352 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
353 {
354         int i;
355         for (i = 0;i < verts;i++)
356         {
357                 out[0] = r;
358                 out[1] = g;
359                 out[2] = b;
360                 out[3] = a;
361                 out += 4;
362         }
363 }
364
365 // FIXME: move this to client?
366 void FOG_clear(void)
367 {
368         if (gamemode == GAME_NEHAHRA)
369         {
370                 Cvar_Set("gl_fogenable", "0");
371                 Cvar_Set("gl_fogdensity", "0.2");
372                 Cvar_Set("gl_fogred", "0.3");
373                 Cvar_Set("gl_foggreen", "0.3");
374                 Cvar_Set("gl_fogblue", "0.3");
375         }
376         r_refdef.fog_density = 0;
377         r_refdef.fog_red = 0;
378         r_refdef.fog_green = 0;
379         r_refdef.fog_blue = 0;
380         r_refdef.fog_alpha = 1;
381         r_refdef.fog_start = 0;
382         r_refdef.fog_end = 16384;
383         r_refdef.fog_height = 1<<30;
384         r_refdef.fog_fadedepth = 128;
385         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
386 }
387
388 static void R_BuildBlankTextures(void)
389 {
390         unsigned char data[4];
391         data[2] = 128; // normal X
392         data[1] = 128; // normal Y
393         data[0] = 255; // normal Z
394         data[3] = 255; // height
395         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396         data[0] = 255;
397         data[1] = 255;
398         data[2] = 255;
399         data[3] = 255;
400         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401         data[0] = 128;
402         data[1] = 128;
403         data[2] = 128;
404         data[3] = 255;
405         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406         data[0] = 0;
407         data[1] = 0;
408         data[2] = 0;
409         data[3] = 255;
410         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
411 }
412
413 static void R_BuildNoTexture(void)
414 {
415         int x, y;
416         unsigned char pix[16][16][4];
417         // this makes a light grey/dark grey checkerboard texture
418         for (y = 0;y < 16;y++)
419         {
420                 for (x = 0;x < 16;x++)
421                 {
422                         if ((y < 8) ^ (x < 8))
423                         {
424                                 pix[y][x][0] = 128;
425                                 pix[y][x][1] = 128;
426                                 pix[y][x][2] = 128;
427                                 pix[y][x][3] = 255;
428                         }
429                         else
430                         {
431                                 pix[y][x][0] = 64;
432                                 pix[y][x][1] = 64;
433                                 pix[y][x][2] = 64;
434                                 pix[y][x][3] = 255;
435                         }
436                 }
437         }
438         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
439 }
440
441 static void R_BuildWhiteCube(void)
442 {
443         unsigned char data[6*1*1*4];
444         memset(data, 255, sizeof(data));
445         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446 }
447
448 static void R_BuildNormalizationCube(void)
449 {
450         int x, y, side;
451         vec3_t v;
452         vec_t s, t, intensity;
453 #define NORMSIZE 64
454         unsigned char *data;
455         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
456         for (side = 0;side < 6;side++)
457         {
458                 for (y = 0;y < NORMSIZE;y++)
459                 {
460                         for (x = 0;x < NORMSIZE;x++)
461                         {
462                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
463                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464                                 switch(side)
465                                 {
466                                 default:
467                                 case 0:
468                                         v[0] = 1;
469                                         v[1] = -t;
470                                         v[2] = -s;
471                                         break;
472                                 case 1:
473                                         v[0] = -1;
474                                         v[1] = -t;
475                                         v[2] = s;
476                                         break;
477                                 case 2:
478                                         v[0] = s;
479                                         v[1] = 1;
480                                         v[2] = t;
481                                         break;
482                                 case 3:
483                                         v[0] = s;
484                                         v[1] = -1;
485                                         v[2] = -t;
486                                         break;
487                                 case 4:
488                                         v[0] = s;
489                                         v[1] = -t;
490                                         v[2] = 1;
491                                         break;
492                                 case 5:
493                                         v[0] = -s;
494                                         v[1] = -t;
495                                         v[2] = -1;
496                                         break;
497                                 }
498                                 intensity = 127.0f / sqrt(DotProduct(v, v));
499                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
500                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
501                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
502                                 data[((side*64+y)*64+x)*4+3] = 255;
503                         }
504                 }
505         }
506         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
507         Mem_Free(data);
508 }
509
510 static void R_BuildFogTexture(void)
511 {
512         int x, b;
513 #define FOGWIDTH 256
514         unsigned char data1[FOGWIDTH][4];
515         //unsigned char data2[FOGWIDTH][4];
516         double d, r, alpha;
517
518         r_refdef.fogmasktable_start = r_refdef.fog_start;
519         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
520         r_refdef.fogmasktable_range = r_refdef.fogrange;
521         r_refdef.fogmasktable_density = r_refdef.fog_density;
522
523         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
524         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
525         {
526                 d = (x * r - r_refdef.fogmasktable_start);
527                 if(developer_extra.integer)
528                         Con_DPrintf("%f ", d);
529                 d = max(0, d);
530                 if (r_fog_exp2.integer)
531                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
532                 else
533                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
534                 if(developer_extra.integer)
535                         Con_DPrintf(" : %f ", alpha);
536                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
537                 if(developer_extra.integer)
538                         Con_DPrintf(" = %f\n", alpha);
539                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
540         }
541
542         for (x = 0;x < FOGWIDTH;x++)
543         {
544                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
545                 data1[x][0] = b;
546                 data1[x][1] = b;
547                 data1[x][2] = b;
548                 data1[x][3] = 255;
549                 //data2[x][0] = 255 - b;
550                 //data2[x][1] = 255 - b;
551                 //data2[x][2] = 255 - b;
552                 //data2[x][3] = 255;
553         }
554         if (r_texture_fogattenuation)
555         {
556                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558         }
559         else
560         {
561                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
562                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
563         }
564 }
565
566 static void R_BuildFogHeightTexture(void)
567 {
568         unsigned char *inpixels;
569         int size;
570         int x;
571         int y;
572         int j;
573         float c[4];
574         float f;
575         inpixels = NULL;
576         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
577         if (r_refdef.fogheighttexturename[0])
578                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
579         if (!inpixels)
580         {
581                 r_refdef.fog_height_tablesize = 0;
582                 if (r_texture_fogheighttexture)
583                         R_FreeTexture(r_texture_fogheighttexture);
584                 r_texture_fogheighttexture = NULL;
585                 if (r_refdef.fog_height_table2d)
586                         Mem_Free(r_refdef.fog_height_table2d);
587                 r_refdef.fog_height_table2d = NULL;
588                 if (r_refdef.fog_height_table1d)
589                         Mem_Free(r_refdef.fog_height_table1d);
590                 r_refdef.fog_height_table1d = NULL;
591                 return;
592         }
593         size = image_width;
594         r_refdef.fog_height_tablesize = size;
595         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
596         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
597         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
598         Mem_Free(inpixels);
599         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
600         // average fog color table accounting for every fog layer between a point
601         // and the camera.  (Note: attenuation is handled separately!)
602         for (y = 0;y < size;y++)
603         {
604                 for (x = 0;x < size;x++)
605                 {
606                         Vector4Clear(c);
607                         f = 0;
608                         if (x < y)
609                         {
610                                 for (j = x;j <= y;j++)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         else
617                         {
618                                 for (j = x;j >= y;j--)
619                                 {
620                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
621                                         f++;
622                                 }
623                         }
624                         f = 1.0f / f;
625                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
626                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
627                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
628                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
629                 }
630         }
631         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
632 }
633
634 //=======================================================================================================================================================
635
636 static const char *builtinshaderstrings[] =
637 {
638 #include "shader_glsl.h"
639 0
640 };
641
642 const char *builtinhlslshaderstrings[] =
643 {
644 #include "shader_hlsl.h"
645 0
646 };
647
648 //=======================================================================================================================================================
649
650 typedef struct shaderpermutationinfo_s
651 {
652         const char *pretext;
653         const char *name;
654 }
655 shaderpermutationinfo_t;
656
657 typedef struct shadermodeinfo_s
658 {
659         const char *sourcebasename;
660         const char *extension;
661         const char **builtinshaderstrings;
662         const char *pretext;
663         const char *name;
664         char *filename;
665         char *builtinstring;
666         int builtincrc;
667 }
668 shadermodeinfo_t;
669
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
672 {
673         {"#define USEDIFFUSE\n", " diffuse"},
674         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
675         {"#define USEVIEWTINT\n", " viewtint"},
676         {"#define USECOLORMAPPING\n", " colormapping"},
677         {"#define USESATURATION\n", " saturation"},
678         {"#define USEFOGINSIDE\n", " foginside"},
679         {"#define USEFOGOUTSIDE\n", " fogoutside"},
680         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
681         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
682         {"#define USEGAMMARAMPS\n", " gammaramps"},
683         {"#define USECUBEFILTER\n", " cubefilter"},
684         {"#define USEGLOW\n", " glow"},
685         {"#define USEBLOOM\n", " bloom"},
686         {"#define USESPECULAR\n", " specular"},
687         {"#define USEPOSTPROCESSING\n", " postprocessing"},
688         {"#define USEREFLECTION\n", " reflection"},
689         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
690         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
691         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
692         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
693         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
694         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
695         {"#define USEALPHAKILL\n", " alphakill"},
696         {"#define USEREFLECTCUBE\n", " reflectcube"},
697         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
698         {"#define USEBOUNCEGRID\n", " bouncegrid"},
699         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
700         {"#define USETRIPPY\n", " trippy"},
701         {"#define USEDEPTHRGB\n", " depthrgb"},
702         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
703         {"#define USESKELETAL\n", " skeletal"},
704         {"#define USEOCCLUDE\n", " occlude"}
705 };
706
707 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
708 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
709 {
710         // SHADERLANGUAGE_GLSL
711         {
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
725                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
726                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
727                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729         },
730         // SHADERLANGUAGE_HLSL
731         {
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
745                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
746                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
747                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
748                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
749         },
750 };
751
752 struct r_glsl_permutation_s;
753 typedef struct r_glsl_permutation_s
754 {
755         /// hash lookup data
756         struct r_glsl_permutation_s *hashnext;
757         unsigned int mode;
758         dpuint64 permutation;
759
760         /// indicates if we have tried compiling this permutation already
761         qboolean compiled;
762         /// 0 if compilation failed
763         int program;
764         // texture units assigned to each detected uniform
765         int tex_Texture_First;
766         int tex_Texture_Second;
767         int tex_Texture_GammaRamps;
768         int tex_Texture_Normal;
769         int tex_Texture_Color;
770         int tex_Texture_Gloss;
771         int tex_Texture_Glow;
772         int tex_Texture_SecondaryNormal;
773         int tex_Texture_SecondaryColor;
774         int tex_Texture_SecondaryGloss;
775         int tex_Texture_SecondaryGlow;
776         int tex_Texture_Pants;
777         int tex_Texture_Shirt;
778         int tex_Texture_FogHeightTexture;
779         int tex_Texture_FogMask;
780         int tex_Texture_Lightmap;
781         int tex_Texture_Deluxemap;
782         int tex_Texture_Attenuation;
783         int tex_Texture_Cube;
784         int tex_Texture_Refraction;
785         int tex_Texture_Reflection;
786         int tex_Texture_ShadowMap2D;
787         int tex_Texture_CubeProjection;
788         int tex_Texture_ScreenNormalMap;
789         int tex_Texture_ScreenDiffuse;
790         int tex_Texture_ScreenSpecular;
791         int tex_Texture_ReflectMask;
792         int tex_Texture_ReflectCube;
793         int tex_Texture_BounceGrid;
794         /// locations of detected uniforms in program object, or -1 if not found
795         int loc_Texture_First;
796         int loc_Texture_Second;
797         int loc_Texture_GammaRamps;
798         int loc_Texture_Normal;
799         int loc_Texture_Color;
800         int loc_Texture_Gloss;
801         int loc_Texture_Glow;
802         int loc_Texture_SecondaryNormal;
803         int loc_Texture_SecondaryColor;
804         int loc_Texture_SecondaryGloss;
805         int loc_Texture_SecondaryGlow;
806         int loc_Texture_Pants;
807         int loc_Texture_Shirt;
808         int loc_Texture_FogHeightTexture;
809         int loc_Texture_FogMask;
810         int loc_Texture_Lightmap;
811         int loc_Texture_Deluxemap;
812         int loc_Texture_Attenuation;
813         int loc_Texture_Cube;
814         int loc_Texture_Refraction;
815         int loc_Texture_Reflection;
816         int loc_Texture_ShadowMap2D;
817         int loc_Texture_CubeProjection;
818         int loc_Texture_ScreenNormalMap;
819         int loc_Texture_ScreenDiffuse;
820         int loc_Texture_ScreenSpecular;
821         int loc_Texture_ReflectMask;
822         int loc_Texture_ReflectCube;
823         int loc_Texture_BounceGrid;
824         int loc_Alpha;
825         int loc_BloomBlur_Parameters;
826         int loc_ClientTime;
827         int loc_Color_Ambient;
828         int loc_Color_Diffuse;
829         int loc_Color_Specular;
830         int loc_Color_Glow;
831         int loc_Color_Pants;
832         int loc_Color_Shirt;
833         int loc_DeferredColor_Ambient;
834         int loc_DeferredColor_Diffuse;
835         int loc_DeferredColor_Specular;
836         int loc_DeferredMod_Diffuse;
837         int loc_DeferredMod_Specular;
838         int loc_DistortScaleRefractReflect;
839         int loc_EyePosition;
840         int loc_FogColor;
841         int loc_FogHeightFade;
842         int loc_FogPlane;
843         int loc_FogPlaneViewDist;
844         int loc_FogRangeRecip;
845         int loc_LightColor;
846         int loc_LightDir;
847         int loc_LightPosition;
848         int loc_OffsetMapping_ScaleSteps;
849         int loc_OffsetMapping_LodDistance;
850         int loc_OffsetMapping_Bias;
851         int loc_PixelSize;
852         int loc_ReflectColor;
853         int loc_ReflectFactor;
854         int loc_ReflectOffset;
855         int loc_RefractColor;
856         int loc_Saturation;
857         int loc_ScreenCenterRefractReflect;
858         int loc_ScreenScaleRefractReflect;
859         int loc_ScreenToDepth;
860         int loc_ShadowMap_Parameters;
861         int loc_ShadowMap_TextureScale;
862         int loc_SpecularPower;
863         int loc_Skeletal_Transform12;
864         int loc_UserVec1;
865         int loc_UserVec2;
866         int loc_UserVec3;
867         int loc_UserVec4;
868         int loc_ViewTintColor;
869         int loc_ViewToLight;
870         int loc_ModelToLight;
871         int loc_TexMatrix;
872         int loc_BackgroundTexMatrix;
873         int loc_ModelViewProjectionMatrix;
874         int loc_ModelViewMatrix;
875         int loc_PixelToScreenTexCoord;
876         int loc_ModelToReflectCube;
877         int loc_ShadowMapMatrix;
878         int loc_BloomColorSubtract;
879         int loc_NormalmapScrollBlend;
880         int loc_BounceGridMatrix;
881         int loc_BounceGridIntensity;
882         /// uniform block bindings
883         int ubibind_Skeletal_Transform12_UniformBlock;
884         /// uniform block indices
885         int ubiloc_Skeletal_Transform12_UniformBlock;
886 }
887 r_glsl_permutation_t;
888
889 #define SHADERPERMUTATION_HASHSIZE 256
890
891
892 // non-degradable "lightweight" shader parameters to keep the permutations simpler
893 // these can NOT degrade! only use for simple stuff
894 enum
895 {
896         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
897         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
898         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
899         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
900         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
901         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
902         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
903         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
904         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
905         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
906         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
907         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
908         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
909         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
910 };
911 #define SHADERSTATICPARMS_COUNT 14
912
913 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
914 static int shaderstaticparms_count = 0;
915
916 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
917 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
918
919 extern qboolean r_shadow_shadowmapsampler;
920 extern int r_shadow_shadowmappcf;
921 qboolean R_CompileShader_CheckStaticParms(void)
922 {
923         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
924         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
925         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
926
927         // detect all
928         if (r_glsl_saturation_redcompensate.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
930         if (r_glsl_vertextextureblend_usebothalphas.integer)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
932         if (r_shadow_glossexact.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
934         if (r_glsl_postprocess.integer)
935         {
936                 if (r_glsl_postprocess_uservec1_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
938                 if (r_glsl_postprocess_uservec2_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
940                 if (r_glsl_postprocess_uservec3_enable.integer)
941                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
942                 if (r_glsl_postprocess_uservec4_enable.integer)
943                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
944         }
945         if (r_fxaa.integer)
946                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
947         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
948                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
949
950         if (r_shadow_shadowmapsampler)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
952         if (r_shadow_shadowmappcf > 1)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
954         else if (r_shadow_shadowmappcf)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
956         if (r_celshading.integer)
957                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
958         if (r_celoutlines.integer)
959                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
960
961         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
962 }
963
964 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
965         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
966                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
967         else \
968                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
969 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
970 {
971         shaderstaticparms_count = 0;
972
973         // emit all
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
984         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
985         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
986         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
987         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
988 }
989
990 /// information about each possible shader permutation
991 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
992 /// currently selected permutation
993 r_glsl_permutation_t *r_glsl_permutation;
994 /// storage for permutations linked in the hash table
995 memexpandablearray_t r_glsl_permutationarray;
996
997 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
998 {
999         //unsigned int hashdepth = 0;
1000         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1001         r_glsl_permutation_t *p;
1002         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1003         {
1004                 if (p->mode == mode && p->permutation == permutation)
1005                 {
1006                         //if (hashdepth > 10)
1007                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1008                         return p;
1009                 }
1010                 //hashdepth++;
1011         }
1012         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1013         p->mode = mode;
1014         p->permutation = permutation;
1015         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1016         r_glsl_permutationhash[mode][hashindex] = p;
1017         //if (hashdepth > 10)
1018         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1019         return p;
1020 }
1021
1022 static char *R_ShaderStrCat(const char **strings)
1023 {
1024         char *string, *s;
1025         const char **p = strings;
1026         const char *t;
1027         size_t len = 0;
1028         for (p = strings;(t = *p);p++)
1029                 len += strlen(t);
1030         len++;
1031         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1032         len = 0;
1033         for (p = strings;(t = *p);p++)
1034         {
1035                 len = strlen(t);
1036                 memcpy(s, t, len);
1037                 s += len;
1038         }
1039         *s = 0;
1040         return string;
1041 }
1042
1043 static char *R_ShaderStrCat(const char **strings);
1044 static void R_InitShaderModeInfo(void)
1045 {
1046         int i, language;
1047         shadermodeinfo_t *modeinfo;
1048         // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1049         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1050         {
1051                 for (i = 0; i < SHADERMODE_COUNT; i++)
1052                 {
1053                         char filename[MAX_QPATH];
1054                         modeinfo = &shadermodeinfo[language][i];
1055                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1056                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1057                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1058                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1059                 }
1060         }
1061 }
1062
1063 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1064 {
1065         char *shaderstring;
1066         // if the mode has no filename we have to return the builtin string
1067         if (builtinonly || !modeinfo->filename)
1068                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1069         // note that FS_LoadFile appends a 0 byte to make it a valid string
1070         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1071         if (shaderstring)
1072         {
1073                 if (printfromdisknotice)
1074                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1075                 return shaderstring;
1076         }
1077         // fall back to builtinstring
1078         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1079 }
1080
1081 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1082 {
1083         int i;
1084         int ubibind;
1085         int sampler;
1086         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1087         char *sourcestring;
1088         char permutationname[256];
1089         int vertstrings_count = 0;
1090         int geomstrings_count = 0;
1091         int fragstrings_count = 0;
1092         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095
1096         if (p->compiled)
1097                 return;
1098         p->compiled = true;
1099         p->program = 0;
1100
1101         permutationname[0] = 0;
1102         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1103
1104         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1105
1106         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1107         if(vid.support.glshaderversion >= 140)
1108         {
1109                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1110                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1111                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1112                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1113                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1114                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1115         }
1116         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1117         else if(vid.support.glshaderversion >= 130)
1118         {
1119                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1120                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1121                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1122                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1123                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1124                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1125         }
1126         // if we can do #version 120, we should (this adds the invariant keyword)
1127         else if(vid.support.glshaderversion >= 120)
1128         {
1129                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1130                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1131                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1132                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1133                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1134                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1135         }
1136         // GLES also adds several things from GLSL120
1137         switch(vid.renderpath)
1138         {
1139         case RENDERPATH_GLES2:
1140                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1141                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1142                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1143                 break;
1144         default:
1145                 break;
1146         }
1147
1148         // the first pretext is which type of shader to compile as
1149         // (later these will all be bound together as a program object)
1150         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1151         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1152         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1153
1154         // the second pretext is the mode (for example a light source)
1155         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1156         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1157         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1158         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1159
1160         // now add all the permutation pretexts
1161         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1162         {
1163                 if (permutation & (1ll<<i))
1164                 {
1165                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1166                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1167                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1168                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1169                 }
1170                 else
1171                 {
1172                         // keep line numbers correct
1173                         vertstrings_list[vertstrings_count++] = "\n";
1174                         geomstrings_list[geomstrings_count++] = "\n";
1175                         fragstrings_list[fragstrings_count++] = "\n";
1176                 }
1177         }
1178
1179         // add static parms
1180         R_CompileShader_AddStaticParms(mode, permutation);
1181         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182         vertstrings_count += shaderstaticparms_count;
1183         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184         geomstrings_count += shaderstaticparms_count;
1185         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186         fragstrings_count += shaderstaticparms_count;
1187
1188         // now append the shader text itself
1189         vertstrings_list[vertstrings_count++] = sourcestring;
1190         geomstrings_list[geomstrings_count++] = sourcestring;
1191         fragstrings_list[fragstrings_count++] = sourcestring;
1192
1193         // compile the shader program
1194         if (vertstrings_count + geomstrings_count + fragstrings_count)
1195                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1196         if (p->program)
1197         {
1198                 CHECKGLERROR
1199                 qglUseProgram(p->program);CHECKGLERROR
1200                 // look up all the uniform variable names we care about, so we don't
1201                 // have to look them up every time we set them
1202
1203 #if 0
1204                 // debugging aid
1205                 {
1206                         GLint activeuniformindex = 0;
1207                         GLint numactiveuniforms = 0;
1208                         char uniformname[128];
1209                         GLsizei uniformnamelength = 0;
1210                         GLint uniformsize = 0;
1211                         GLenum uniformtype = 0;
1212                         memset(uniformname, 0, sizeof(uniformname));
1213                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1214                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1215                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1216                         {
1217                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1218                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1219                         }
1220                 }
1221 #endif
1222
1223                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1224                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1225                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1226                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1227                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1228                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1229                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1230                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1231                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1232                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1233                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1234                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1235                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1236                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1237                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1238                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1239                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1240                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1241                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1242                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1243                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1244                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1245                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1246                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1247                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1248                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1249                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1250                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1251                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1252                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1253                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1254                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1255                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1256                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1257                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1258                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1259                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1260                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1261                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1262                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1263                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1264                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1265                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1266                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1267                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1268                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1269                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1270                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1271                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1272                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1273                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1274                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1275                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1276                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1277                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1278                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1279                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1280                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1281                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1282                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1283                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1284                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1285                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1286                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1287                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1288                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1289                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1290                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1291                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1292                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1293                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1294                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1295                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1296                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1297                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1298                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1299                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1300                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1301                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1302                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1303                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1304                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1305                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1306                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1307                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1308                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1309                 // initialize the samplers to refer to the texture units we use
1310                 p->tex_Texture_First = -1;
1311                 p->tex_Texture_Second = -1;
1312                 p->tex_Texture_GammaRamps = -1;
1313                 p->tex_Texture_Normal = -1;
1314                 p->tex_Texture_Color = -1;
1315                 p->tex_Texture_Gloss = -1;
1316                 p->tex_Texture_Glow = -1;
1317                 p->tex_Texture_SecondaryNormal = -1;
1318                 p->tex_Texture_SecondaryColor = -1;
1319                 p->tex_Texture_SecondaryGloss = -1;
1320                 p->tex_Texture_SecondaryGlow = -1;
1321                 p->tex_Texture_Pants = -1;
1322                 p->tex_Texture_Shirt = -1;
1323                 p->tex_Texture_FogHeightTexture = -1;
1324                 p->tex_Texture_FogMask = -1;
1325                 p->tex_Texture_Lightmap = -1;
1326                 p->tex_Texture_Deluxemap = -1;
1327                 p->tex_Texture_Attenuation = -1;
1328                 p->tex_Texture_Cube = -1;
1329                 p->tex_Texture_Refraction = -1;
1330                 p->tex_Texture_Reflection = -1;
1331                 p->tex_Texture_ShadowMap2D = -1;
1332                 p->tex_Texture_CubeProjection = -1;
1333                 p->tex_Texture_ScreenNormalMap = -1;
1334                 p->tex_Texture_ScreenDiffuse = -1;
1335                 p->tex_Texture_ScreenSpecular = -1;
1336                 p->tex_Texture_ReflectMask = -1;
1337                 p->tex_Texture_ReflectCube = -1;
1338                 p->tex_Texture_BounceGrid = -1;
1339                 // bind the texture samplers in use
1340                 sampler = 0;
1341                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1342                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1343                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1344                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1345                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1346                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1347                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1348                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1349                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1350                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1351                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1352                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1353                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1354                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1355                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1356                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1357                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1358                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1359                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1360                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1361                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1362                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1363                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1364                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1365                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1366                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1367                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1368                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1369                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1370                 // get the uniform block indices so we can bind them
1371 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1372                 if (vid.support.arb_uniform_buffer_object)
1373                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1374                 else
1375 #endif
1376                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1377                 // clear the uniform block bindings
1378                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1379                 // bind the uniform blocks in use
1380                 ubibind = 0;
1381 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1382                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1383 #endif
1384                 // we're done compiling and setting up the shader, at least until it is used
1385                 CHECKGLERROR
1386                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1387         }
1388         else
1389                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1390
1391         // free the strings
1392         if (sourcestring)
1393                 Mem_Free(sourcestring);
1394 }
1395
1396 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1397 {
1398         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1399         if (r_glsl_permutation != perm)
1400         {
1401                 r_glsl_permutation = perm;
1402                 if (!r_glsl_permutation->program)
1403                 {
1404                         if (!r_glsl_permutation->compiled)
1405                         {
1406                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1407                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1408                         }
1409                         if (!r_glsl_permutation->program)
1410                         {
1411                                 // remove features until we find a valid permutation
1412                                 int i;
1413                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1414                                 {
1415                                         // reduce i more quickly whenever it would not remove any bits
1416                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1417                                         if (!(permutation & j))
1418                                                 continue;
1419                                         permutation -= j;
1420                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1421                                         if (!r_glsl_permutation->compiled)
1422                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1423                                         if (r_glsl_permutation->program)
1424                                                 break;
1425                                 }
1426                                 if (i >= SHADERPERMUTATION_COUNT)
1427                                 {
1428                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1429                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1430                                         qglUseProgram(0);CHECKGLERROR
1431                                         return; // no bit left to clear, entire mode is broken
1432                                 }
1433                         }
1434                 }
1435                 CHECKGLERROR
1436                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1437         }
1438         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1439         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1440         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1441         CHECKGLERROR
1442 }
1443
1444 #ifdef SUPPORTD3D
1445
1446 #ifdef SUPPORTD3D
1447 #include <d3d9.h>
1448 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1449 extern D3DCAPS9 vid_d3d9caps;
1450 #endif
1451
1452 struct r_hlsl_permutation_s;
1453 typedef struct r_hlsl_permutation_s
1454 {
1455         /// hash lookup data
1456         struct r_hlsl_permutation_s *hashnext;
1457         unsigned int mode;
1458         dpuint64 permutation;
1459
1460         /// indicates if we have tried compiling this permutation already
1461         qboolean compiled;
1462         /// NULL if compilation failed
1463         IDirect3DVertexShader9 *vertexshader;
1464         IDirect3DPixelShader9 *pixelshader;
1465 }
1466 r_hlsl_permutation_t;
1467
1468 typedef enum D3DVSREGISTER_e
1469 {
1470         D3DVSREGISTER_TexMatrix = 0, // float4x4
1471         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1472         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1473         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1474         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1475         D3DVSREGISTER_ModelToLight = 20, // float4x4
1476         D3DVSREGISTER_EyePosition = 24,
1477         D3DVSREGISTER_FogPlane = 25,
1478         D3DVSREGISTER_LightDir = 26,
1479         D3DVSREGISTER_LightPosition = 27,
1480 }
1481 D3DVSREGISTER_t;
1482
1483 typedef enum D3DPSREGISTER_e
1484 {
1485         D3DPSREGISTER_Alpha = 0,
1486         D3DPSREGISTER_BloomBlur_Parameters = 1,
1487         D3DPSREGISTER_ClientTime = 2,
1488         D3DPSREGISTER_Color_Ambient = 3,
1489         D3DPSREGISTER_Color_Diffuse = 4,
1490         D3DPSREGISTER_Color_Specular = 5,
1491         D3DPSREGISTER_Color_Glow = 6,
1492         D3DPSREGISTER_Color_Pants = 7,
1493         D3DPSREGISTER_Color_Shirt = 8,
1494         D3DPSREGISTER_DeferredColor_Ambient = 9,
1495         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1496         D3DPSREGISTER_DeferredColor_Specular = 11,
1497         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1498         D3DPSREGISTER_DeferredMod_Specular = 13,
1499         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1500         D3DPSREGISTER_EyePosition = 15, // unused
1501         D3DPSREGISTER_FogColor = 16,
1502         D3DPSREGISTER_FogHeightFade = 17,
1503         D3DPSREGISTER_FogPlane = 18,
1504         D3DPSREGISTER_FogPlaneViewDist = 19,
1505         D3DPSREGISTER_FogRangeRecip = 20,
1506         D3DPSREGISTER_LightColor = 21,
1507         D3DPSREGISTER_LightDir = 22, // unused
1508         D3DPSREGISTER_LightPosition = 23,
1509         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1510         D3DPSREGISTER_PixelSize = 25,
1511         D3DPSREGISTER_ReflectColor = 26,
1512         D3DPSREGISTER_ReflectFactor = 27,
1513         D3DPSREGISTER_ReflectOffset = 28,
1514         D3DPSREGISTER_RefractColor = 29,
1515         D3DPSREGISTER_Saturation = 30,
1516         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1517         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1518         D3DPSREGISTER_ScreenToDepth = 33,
1519         D3DPSREGISTER_ShadowMap_Parameters = 34,
1520         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1521         D3DPSREGISTER_SpecularPower = 36,
1522         D3DPSREGISTER_UserVec1 = 37,
1523         D3DPSREGISTER_UserVec2 = 38,
1524         D3DPSREGISTER_UserVec3 = 39,
1525         D3DPSREGISTER_UserVec4 = 40,
1526         D3DPSREGISTER_ViewTintColor = 41,
1527         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1528         D3DPSREGISTER_BloomColorSubtract = 43,
1529         D3DPSREGISTER_ViewToLight = 44, // float4x4
1530         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1531         D3DPSREGISTER_NormalmapScrollBlend = 52,
1532         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1533         D3DPSREGISTER_OffsetMapping_Bias = 54,
1534         // next at 54
1535 }
1536 D3DPSREGISTER_t;
1537
1538 /// information about each possible shader permutation
1539 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1540 /// currently selected permutation
1541 r_hlsl_permutation_t *r_hlsl_permutation;
1542 /// storage for permutations linked in the hash table
1543 memexpandablearray_t r_hlsl_permutationarray;
1544
1545 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1546 {
1547         //unsigned int hashdepth = 0;
1548         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1549         r_hlsl_permutation_t *p;
1550         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1551         {
1552                 if (p->mode == mode && p->permutation == permutation)
1553                 {
1554                         //if (hashdepth > 10)
1555                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1556                         return p;
1557                 }
1558                 //hashdepth++;
1559         }
1560         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1561         p->mode = mode;
1562         p->permutation = permutation;
1563         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1564         r_hlsl_permutationhash[mode][hashindex] = p;
1565         //if (hashdepth > 10)
1566         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1567         return p;
1568 }
1569
1570 #include <d3dx9.h>
1571 //#include <d3dx9shader.h>
1572 //#include <d3dx9mesh.h>
1573
1574 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1575 {
1576         DWORD *vsbin = NULL;
1577         DWORD *psbin = NULL;
1578         fs_offset_t vsbinsize;
1579         fs_offset_t psbinsize;
1580 //      IDirect3DVertexShader9 *vs = NULL;
1581 //      IDirect3DPixelShader9 *ps = NULL;
1582         ID3DXBuffer *vslog = NULL;
1583         ID3DXBuffer *vsbuffer = NULL;
1584         ID3DXConstantTable *vsconstanttable = NULL;
1585         ID3DXBuffer *pslog = NULL;
1586         ID3DXBuffer *psbuffer = NULL;
1587         ID3DXConstantTable *psconstanttable = NULL;
1588         int vsresult = 0;
1589         int psresult = 0;
1590         char temp[MAX_INPUTLINE];
1591         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1592         char vabuf[1024];
1593         qboolean debugshader = gl_paranoid.integer != 0;
1594         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1595         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596         if (!debugshader)
1597         {
1598                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1599                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1600         }
1601         if ((!vsbin && vertstring) || (!psbin && fragstring))
1602         {
1603                 const char* dllnames_d3dx9 [] =
1604                 {
1605                         "d3dx9_43.dll",
1606                         "d3dx9_42.dll",
1607                         "d3dx9_41.dll",
1608                         "d3dx9_40.dll",
1609                         "d3dx9_39.dll",
1610                         "d3dx9_38.dll",
1611                         "d3dx9_37.dll",
1612                         "d3dx9_36.dll",
1613                         "d3dx9_35.dll",
1614                         "d3dx9_34.dll",
1615                         "d3dx9_33.dll",
1616                         "d3dx9_32.dll",
1617                         "d3dx9_31.dll",
1618                         "d3dx9_30.dll",
1619                         "d3dx9_29.dll",
1620                         "d3dx9_28.dll",
1621                         "d3dx9_27.dll",
1622                         "d3dx9_26.dll",
1623                         "d3dx9_25.dll",
1624                         "d3dx9_24.dll",
1625                         NULL
1626                 };
1627                 dllhandle_t d3dx9_dll = NULL;
1628                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1629                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1630                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631                 dllfunction_t d3dx9_dllfuncs[] =
1632                 {
1633                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1634                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1635                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1636                         {NULL, NULL}
1637                 };
1638                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1639 #ifndef ID3DXBuffer_GetBufferPointer
1640 #if !defined(__cplusplus) || defined(CINTERFACE)
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1643 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1644 #else
1645 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1646 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1647 #define ID3DXBuffer_Release(p)            (p)->Release()
1648 #endif
1649 #endif
1650                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1651                 {
1652                         DWORD shaderflags = 0;
1653                         if (debugshader)
1654                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1655                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1656                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1657                         if (vertstring && vertstring[0])
1658                         {
1659                                 if (debugshader)
1660                                 {
1661                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1662                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1663                                 }
1664                                 else
1665                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1666                                 if (vsbuffer)
1667                                 {
1668                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1669                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1670                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1671                                         ID3DXBuffer_Release(vsbuffer);
1672                                 }
1673                                 if (vslog)
1674                                 {
1675                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1676                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1677                                         ID3DXBuffer_Release(vslog);
1678                                 }
1679                         }
1680                         if (fragstring && fragstring[0])
1681                         {
1682                                 if (debugshader)
1683                                 {
1684                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1685                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1686                                 }
1687                                 else
1688                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1689                                 if (psbuffer)
1690                                 {
1691                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1692                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1693                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1694                                         ID3DXBuffer_Release(psbuffer);
1695                                 }
1696                                 if (pslog)
1697                                 {
1698                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1699                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1700                                         ID3DXBuffer_Release(pslog);
1701                                 }
1702                         }
1703                         Sys_UnloadLibrary(&d3dx9_dll);
1704                 }
1705                 else
1706                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1707         }
1708         if (vsbin && psbin)
1709         {
1710                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1711                 if (FAILED(vsresult))
1712                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1713                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1714                 if (FAILED(psresult))
1715                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1716         }
1717         // free the shader data
1718         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1719         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1720 }
1721
1722 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1723 {
1724         int i;
1725         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1726         int vertstring_length = 0;
1727         int geomstring_length = 0;
1728         int fragstring_length = 0;
1729         char *t;
1730         char *sourcestring;
1731         char *vertstring, *geomstring, *fragstring;
1732         char permutationname[256];
1733         char cachename[256];
1734         int vertstrings_count = 0;
1735         int geomstrings_count = 0;
1736         int fragstrings_count = 0;
1737         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1738         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740
1741         if (p->compiled)
1742                 return;
1743         p->compiled = true;
1744         p->vertexshader = NULL;
1745         p->pixelshader = NULL;
1746
1747         permutationname[0] = 0;
1748         cachename[0] = 0;
1749         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1750
1751         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1752         strlcat(cachename, "hlsl/", sizeof(cachename));
1753
1754         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1755         vertstrings_count = 0;
1756         geomstrings_count = 0;
1757         fragstrings_count = 0;
1758         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1759         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1760         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1761
1762         // the first pretext is which type of shader to compile as
1763         // (later these will all be bound together as a program object)
1764         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1765         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1766         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1767
1768         // the second pretext is the mode (for example a light source)
1769         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1770         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1771         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1772         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1773         strlcat(cachename, modeinfo->name, sizeof(cachename));
1774
1775         // now add all the permutation pretexts
1776         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777         {
1778                 if (permutation & (1ll<<i))
1779                 {
1780                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1781                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1782                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1783                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1784                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1785                 }
1786                 else
1787                 {
1788                         // keep line numbers correct
1789                         vertstrings_list[vertstrings_count++] = "\n";
1790                         geomstrings_list[geomstrings_count++] = "\n";
1791                         fragstrings_list[fragstrings_count++] = "\n";
1792                 }
1793         }
1794
1795         // add static parms
1796         R_CompileShader_AddStaticParms(mode, permutation);
1797         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798         vertstrings_count += shaderstaticparms_count;
1799         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800         geomstrings_count += shaderstaticparms_count;
1801         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802         fragstrings_count += shaderstaticparms_count;
1803
1804         // replace spaces in the cachename with _ characters
1805         for (i = 0;cachename[i];i++)
1806                 if (cachename[i] == ' ')
1807                         cachename[i] = '_';
1808
1809         // now append the shader text itself
1810         vertstrings_list[vertstrings_count++] = sourcestring;
1811         geomstrings_list[geomstrings_count++] = sourcestring;
1812         fragstrings_list[fragstrings_count++] = sourcestring;
1813
1814         vertstring_length = 0;
1815         for (i = 0;i < vertstrings_count;i++)
1816                 vertstring_length += (int)strlen(vertstrings_list[i]);
1817         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1818         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1819                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1820
1821         geomstring_length = 0;
1822         for (i = 0;i < geomstrings_count;i++)
1823                 geomstring_length += (int)strlen(geomstrings_list[i]);
1824         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1825         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1826                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1827
1828         fragstring_length = 0;
1829         for (i = 0;i < fragstrings_count;i++)
1830                 fragstring_length += (int)strlen(fragstrings_list[i]);
1831         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1832         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1833                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1834
1835         // try to load the cached shader, or generate one
1836         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1837
1838         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1839                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1840         else
1841                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1842
1843         // free the strings
1844         if (vertstring)
1845                 Mem_Free(vertstring);
1846         if (geomstring)
1847                 Mem_Free(geomstring);
1848         if (fragstring)
1849                 Mem_Free(fragstring);
1850         if (sourcestring)
1851                 Mem_Free(sourcestring);
1852 }
1853
1854 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1855 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1856 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1857 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1858 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1859 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1860
1861 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1862 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1863 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1864 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1865 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1866 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1867
1868 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1869 {
1870         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1871         if (r_hlsl_permutation != perm)
1872         {
1873                 r_hlsl_permutation = perm;
1874                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875                 {
1876                         if (!r_hlsl_permutation->compiled)
1877                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1878                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1879                         {
1880                                 // remove features until we find a valid permutation
1881                                 int i;
1882                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                                 {
1884                                         // reduce i more quickly whenever it would not remove any bits
1885                                         dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1886                                         if (!(permutation & j))
1887                                                 continue;
1888                                         permutation -= j;
1889                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1890                                         if (!r_hlsl_permutation->compiled)
1891                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1892                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1893                                                 break;
1894                                 }
1895                                 if (i >= SHADERPERMUTATION_COUNT)
1896                                 {
1897                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1898                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1899                                         return; // no bit left to clear, entire mode is broken
1900                                 }
1901                         }
1902                 }
1903                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1904                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1905         }
1906         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1907         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1908         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1909 }
1910 #endif
1911
1912 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1913 {
1914         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1915         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1916         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1917         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1918 }
1919
1920 void R_GLSL_Restart_f(void)
1921 {
1922         unsigned int i, limit;
1923         switch(vid.renderpath)
1924         {
1925         case RENDERPATH_D3D9:
1926 #ifdef SUPPORTD3D
1927                 {
1928                         r_hlsl_permutation_t *p;
1929                         r_hlsl_permutation = NULL;
1930                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1931                         for (i = 0;i < limit;i++)
1932                         {
1933                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1934                                 {
1935                                         if (p->vertexshader)
1936                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1937                                         if (p->pixelshader)
1938                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1939                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1940                                 }
1941                         }
1942                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1943                 }
1944 #endif
1945                 break;
1946         case RENDERPATH_D3D10:
1947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_D3D11:
1950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_GL20:
1953         case RENDERPATH_GLES2:
1954                 {
1955                         r_glsl_permutation_t *p;
1956                         r_glsl_permutation = NULL;
1957                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1958                         for (i = 0;i < limit;i++)
1959                         {
1960                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1961                                 {
1962                                         GL_Backend_FreeProgram(p->program);
1963                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1964                                 }
1965                         }
1966                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1967                 }
1968                 break;
1969         case RENDERPATH_GL11:
1970         case RENDERPATH_GL13:
1971         case RENDERPATH_GLES1:
1972                 break;
1973         case RENDERPATH_SOFT:
1974                 break;
1975         }
1976 }
1977
1978 static void R_GLSL_DumpShader_f(void)
1979 {
1980         int i, language, mode, dupe;
1981         char *text;
1982         shadermodeinfo_t *modeinfo;
1983         qfile_t *file;
1984
1985         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1986         {
1987                 modeinfo = shadermodeinfo[language];
1988                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1989                 {
1990                         // don't dump the same file multiple times (most or all shaders come from the same file)
1991                         for (dupe = mode - 1;dupe >= 0;dupe--)
1992                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1993                                         break;
1994                         if (dupe >= 0)
1995                                 continue;
1996                         text = modeinfo[mode].builtinstring;
1997                         if (!text)
1998                                 continue;
1999                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2000                         if (file)
2001                         {
2002                                 FS_Print(file, "/* The engine may define the following macros:\n");
2003                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2004                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2005                                         FS_Print(file, modeinfo[i].pretext);
2006                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2007                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2008                                 FS_Print(file, "*/\n");
2009                                 FS_Print(file, text);
2010                                 FS_Close(file);
2011                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2012                         }
2013                         else
2014                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2015                 }
2016         }
2017 }
2018
2019 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2020 {
2021         dpuint64 permutation = 0;
2022         if (r_trippy.integer && !notrippy)
2023                 permutation |= SHADERPERMUTATION_TRIPPY;
2024         permutation |= SHADERPERMUTATION_VIEWTINT;
2025         if (first)
2026                 permutation |= SHADERPERMUTATION_DIFFUSE;
2027         if (second)
2028                 permutation |= SHADERPERMUTATION_SPECULAR;
2029         if (texturemode == GL_MODULATE)
2030                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2031         else if (texturemode == GL_ADD)
2032                 permutation |= SHADERPERMUTATION_GLOW;
2033         else if (texturemode == GL_DECAL)
2034                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2035         if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2036                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2037         if (suppresstexalpha)
2038                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2039         if (!second)
2040                 texturemode = GL_MODULATE;
2041         if (vid.allowalphatocoverage)
2042                 GL_AlphaToCoverage(false);
2043         switch (vid.renderpath)
2044         {
2045         case RENDERPATH_D3D9:
2046 #ifdef SUPPORTD3D
2047                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2048                 R_Mesh_TexBind(GL20TU_FIRST , first );
2049                 R_Mesh_TexBind(GL20TU_SECOND, second);
2050                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2051                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2052 #endif
2053                 break;
2054         case RENDERPATH_D3D10:
2055                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056                 break;
2057         case RENDERPATH_D3D11:
2058                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059                 break;
2060         case RENDERPATH_GL20:
2061         case RENDERPATH_GLES2:
2062                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2063                 if (r_glsl_permutation->tex_Texture_First >= 0)
2064                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2065                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2066                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2067                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2068                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2069                 break;
2070         case RENDERPATH_GL13:
2071         case RENDERPATH_GLES1:
2072                 R_Mesh_TexBind(0, first );
2073                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2074                 R_Mesh_TexMatrix(0, NULL);
2075                 R_Mesh_TexBind(1, second);
2076                 if (second)
2077                 {
2078                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2079                         R_Mesh_TexMatrix(1, NULL);
2080                 }
2081                 break;
2082         case RENDERPATH_GL11:
2083                 R_Mesh_TexBind(0, first );
2084                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2085                 R_Mesh_TexMatrix(0, NULL);
2086                 break;
2087         case RENDERPATH_SOFT:
2088                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2089                 R_Mesh_TexBind(GL20TU_FIRST , first );
2090                 R_Mesh_TexBind(GL20TU_SECOND, second);
2091                 break;
2092         }
2093 }
2094
2095 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2096 {
2097         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2098 }
2099
2100 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2101 {
2102         dpuint64 permutation = 0;
2103         if (r_trippy.integer && !notrippy)
2104                 permutation |= SHADERPERMUTATION_TRIPPY;
2105         if (depthrgb)
2106                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2107         if (skeletal)
2108                 permutation |= SHADERPERMUTATION_SKELETAL;
2109
2110         if (vid.allowalphatocoverage)
2111                 GL_AlphaToCoverage(false);
2112         switch (vid.renderpath)
2113         {
2114         case RENDERPATH_D3D9:
2115 #ifdef SUPPORTD3D
2116                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2117 #endif
2118                 break;
2119         case RENDERPATH_D3D10:
2120                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2121                 break;
2122         case RENDERPATH_D3D11:
2123                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2124                 break;
2125         case RENDERPATH_GL20:
2126         case RENDERPATH_GLES2:
2127                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2128 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2129                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2130 #endif
2131                 break;
2132         case RENDERPATH_GL13:
2133         case RENDERPATH_GLES1:
2134                 R_Mesh_TexBind(0, 0);
2135                 R_Mesh_TexBind(1, 0);
2136                 break;
2137         case RENDERPATH_GL11:
2138                 R_Mesh_TexBind(0, 0);
2139                 break;
2140         case RENDERPATH_SOFT:
2141                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2142                 break;
2143         }
2144 }
2145
2146 #define BLENDFUNC_ALLOWS_COLORMOD      1
2147 #define BLENDFUNC_ALLOWS_FOG           2
2148 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2149 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2150 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2151 static int R_BlendFuncFlags(int src, int dst)
2152 {
2153         int r = 0;
2154
2155         // a blendfunc allows colormod if:
2156         // a) it can never keep the destination pixel invariant, or
2157         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2158         // this is to prevent unintended side effects from colormod
2159
2160         // a blendfunc allows fog if:
2161         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2162         // this is to prevent unintended side effects from fog
2163
2164         // these checks are the output of fogeval.pl
2165
2166         r |= BLENDFUNC_ALLOWS_COLORMOD;
2167         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2168         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2169         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2171         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2172         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2173         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2176         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2179         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2180         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2181         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2185         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188
2189         return r;
2190 }
2191
2192 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2193 {
2194         // select a permutation of the lighting shader appropriate to this
2195         // combination of texture, entity, light source, and fogging, only use the
2196         // minimum features necessary to avoid wasting rendering time in the
2197         // fragment shader on features that are not being used
2198         dpuint64 permutation = 0;
2199         unsigned int mode = 0;
2200         int blendfuncflags;
2201         texture_t *t = rsurface.texture;
2202         float m16f[16];
2203         matrix4x4_t tempmatrix;
2204         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2205         if (r_trippy.integer && !notrippy)
2206                 permutation |= SHADERPERMUTATION_TRIPPY;
2207         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2208                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2209         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2210                 permutation |= SHADERPERMUTATION_OCCLUDE;
2211         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2212                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2213         if (rsurfacepass == RSURFPASS_BACKGROUND)
2214         {
2215                 // distorted background
2216                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2217                 {
2218                         mode = SHADERMODE_WATER;
2219                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2220                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2221                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2222                         {
2223                                 // this is the right thing to do for wateralpha
2224                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2225                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2226                         }
2227                         else
2228                         {
2229                                 // this is the right thing to do for entity alpha
2230                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2231                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2232                         }
2233                 }
2234                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2235                 {
2236                         mode = SHADERMODE_REFRACTION;
2237                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2238                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2239                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                 }
2242                 else
2243                 {
2244                         mode = SHADERMODE_GENERIC;
2245                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2246                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2247                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2248                 }
2249                 if (vid.allowalphatocoverage)
2250                         GL_AlphaToCoverage(false);
2251         }
2252         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2253         {
2254                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2255                 {
2256                         switch(t->offsetmapping)
2257                         {
2258                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2259                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2260                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2261                         case OFFSETMAPPING_OFF: break;
2262                         }
2263                 }
2264                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2265                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2266                 // normalmap (deferred prepass), may use alpha test on diffuse
2267                 mode = SHADERMODE_DEFERREDGEOMETRY;
2268                 GL_BlendFunc(GL_ONE, GL_ZERO);
2269                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2270                 if (vid.allowalphatocoverage)
2271                         GL_AlphaToCoverage(false);
2272         }
2273         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2274         {
2275                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2276                 {
2277                         switch(t->offsetmapping)
2278                         {
2279                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2280                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2281                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282                         case OFFSETMAPPING_OFF: break;
2283                         }
2284                 }
2285                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2286                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2287                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2288                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2289                 // light source
2290                 mode = SHADERMODE_LIGHTSOURCE;
2291                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2292                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2293                 if (VectorLength2(rtlightdiffuse) > 0)
2294                         permutation |= SHADERPERMUTATION_DIFFUSE;
2295                 if (VectorLength2(rtlightspecular) > 0)
2296                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2297                 if (r_refdef.fogenabled)
2298                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2299                 if (t->colormapping)
2300                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2301                 if (r_shadow_usingshadowmap2d)
2302                 {
2303                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2304                         if(r_shadow_shadowmapvsdct)
2305                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2306
2307                         if (r_shadow_shadowmap2ddepthbuffer)
2308                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2309                 }
2310                 if (t->reflectmasktexture)
2311                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2312                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2313                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2314                 if (vid.allowalphatocoverage)
2315                         GL_AlphaToCoverage(false);
2316         }
2317         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2318         {
2319                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2320                 {
2321                         switch(t->offsetmapping)
2322                         {
2323                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2324                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2325                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2326                         case OFFSETMAPPING_OFF: break;
2327                         }
2328                 }
2329                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2330                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2331                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2332                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2333                 // directional model lighting
2334                 mode = SHADERMODE_LIGHTDIRECTION;
2335                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2336                         permutation |= SHADERPERMUTATION_GLOW;
2337                 if (VectorLength2(t->render_modellight_diffuse))
2338                         permutation |= SHADERPERMUTATION_DIFFUSE;
2339                 if (VectorLength2(t->render_modellight_specular) > 0)
2340                         permutation |= SHADERPERMUTATION_SPECULAR;
2341                 if (r_refdef.fogenabled)
2342                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2343                 if (t->colormapping)
2344                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2345                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2346                 {
2347                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2348                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2349
2350                         if (r_shadow_shadowmap2ddepthbuffer)
2351                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2352                 }
2353                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2354                         permutation |= SHADERPERMUTATION_REFLECTION;
2355                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2356                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2357                 if (t->reflectmasktexture)
2358                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2359                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2360                 {
2361                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2362                         if (r_shadow_bouncegrid_state.directional)
2363                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2364                 }
2365                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2366                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2367                 // when using alphatocoverage, we don't need alphakill
2368                 if (vid.allowalphatocoverage)
2369                 {
2370                         if (r_transparent_alphatocoverage.integer)
2371                         {
2372                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2373                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2374                         }
2375                         else
2376                                 GL_AlphaToCoverage(false);
2377                 }
2378         }
2379         else
2380         {
2381                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2382                 {
2383                         switch(t->offsetmapping)
2384                         {
2385                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2386                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2387                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2388                         case OFFSETMAPPING_OFF: break;
2389                         }
2390                 }
2391                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2392                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2393                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2394                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2395                 // lightmapped wall
2396                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2397                         permutation |= SHADERPERMUTATION_GLOW;
2398                 if (r_refdef.fogenabled)
2399                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2400                 if (t->colormapping)
2401                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2402                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2403                 {
2404                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2405                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2406
2407                         if (r_shadow_shadowmap2ddepthbuffer)
2408                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2409                 }
2410                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2411                         permutation |= SHADERPERMUTATION_REFLECTION;
2412                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2413                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2414                 if (t->reflectmasktexture)
2415                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2416                 if (FAKELIGHT_ENABLED)
2417                 {
2418                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2419                         mode = SHADERMODE_FAKELIGHT;
2420                         permutation |= SHADERPERMUTATION_DIFFUSE;
2421                         if (VectorLength2(t->render_lightmap_specular) > 0)
2422                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2423                 }
2424                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2425                 {
2426                         // deluxemapping (light direction texture)
2427                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2428                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2429                         else
2430                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2431                         permutation |= SHADERPERMUTATION_DIFFUSE;
2432                         if (VectorLength2(t->render_lightmap_specular) > 0)
2433                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2434                 }
2435                 else if (r_glsl_deluxemapping.integer >= 2)
2436                 {
2437                         // fake deluxemapping (uniform light direction in tangentspace)
2438                         if (rsurface.uselightmaptexture)
2439                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2440                         else
2441                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (VectorLength2(t->render_lightmap_specular) > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (rsurface.uselightmaptexture)
2447                 {
2448                         // ordinary lightmapping (q1bsp, q3bsp)
2449                         mode = SHADERMODE_LIGHTMAP;
2450                 }
2451                 else
2452                 {
2453                         // ordinary vertex coloring (q3bsp)
2454                         mode = SHADERMODE_VERTEXCOLOR;
2455                 }
2456                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2457                 {
2458                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2459                         if (r_shadow_bouncegrid_state.directional)
2460                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2461                 }
2462                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2463                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2464                 // when using alphatocoverage, we don't need alphakill
2465                 if (vid.allowalphatocoverage)
2466                 {
2467                         if (r_transparent_alphatocoverage.integer)
2468                         {
2469                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2470                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2471                         }
2472                         else
2473                                 GL_AlphaToCoverage(false);
2474                 }
2475         }
2476         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2477                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2478         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2479                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2480         switch(vid.renderpath)
2481         {
2482         case RENDERPATH_D3D9:
2483 #ifdef SUPPORTD3D
2484                 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);
2485                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2486                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2487                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2488                 if (mode == SHADERMODE_LIGHTSOURCE)
2489                 {
2490                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2491                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2492                 }
2493                 else
2494                 {
2495                         if (mode == SHADERMODE_LIGHTDIRECTION)
2496                         {
2497                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2498                         }
2499                 }
2500                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2501                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2502                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2503                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2504                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2505
2506                 if (mode == SHADERMODE_LIGHTSOURCE)
2507                 {
2508                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2509                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2510                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2511                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2512                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2513
2514                         // additive passes are only darkened by fog, not tinted
2515                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2516                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2517                 }
2518                 else
2519                 {
2520                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2521                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2522                         if (mode == SHADERMODE_FLATCOLOR)
2523                         {
2524                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2525                         }
2526                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2527                         {
2528                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2529                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2530                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2531                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2532                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2533                         }
2534                         else
2535                         {
2536                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2537                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2538                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2539                         }
2540                         // additive passes are only darkened by fog, not tinted
2541                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2542                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2543                         else
2544                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2545                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2546                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2547                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2548                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2549                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2550                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2551                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2552                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2553                         if (mode == SHADERMODE_WATER)
2554                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2555                 }
2556                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2557                 {
2558                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2559                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2560                 }
2561                 else
2562                 {
2563                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2564                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2565                 }
2566                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2567                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2568                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2569                 if (t->pantstexture)
2570                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2571                 else
2572                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2573                 if (t->shirttexture)
2574                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2575                 else
2576                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2577                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2578                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2579                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2580                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2581                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2582                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2583                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2584                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2585                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2586                         );
2587                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2588                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2589                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2590                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2591
2592                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2593                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2594                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2595                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2596                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2597                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2598                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2599                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2600                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2601                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2602                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2603                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2604                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2605                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2606                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2607                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2608                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2609                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2610                 {
2611                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2612                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2613                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2614                 }
2615                 else
2616                 {
2617                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2618                 }
2619 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2620                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2621                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2622                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2623                 {
2624                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2625                         if (rsurface.rtlight)
2626                         {
2627                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2628                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2629                         }
2630                 }
2631 #endif
2632                 break;
2633         case RENDERPATH_D3D10:
2634                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2635                 break;
2636         case RENDERPATH_D3D11:
2637                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2638                 break;
2639         case RENDERPATH_GL20:
2640         case RENDERPATH_GLES2:
2641                 if (!vid.useinterleavedarrays)
2642                 {
2643                         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);
2644                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2645                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2646                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2647                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2648                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2649                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2650                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2651                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2652                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2653                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2654                 }
2655                 else
2656                 {
2657                         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);
2658                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2659                 }
2660                 // this has to be after RSurf_PrepareVerticesForBatch
2661                 if (rsurface.batchskeletaltransform3x4buffer)
2662                         permutation |= SHADERPERMUTATION_SKELETAL;
2663                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2664 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2665                 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);
2666 #endif
2667                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2668                 if (mode == SHADERMODE_LIGHTSOURCE)
2669                 {
2670                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2671                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2672                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2673                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2674                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2675                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2676         
2677                         // additive passes are only darkened by fog, not tinted
2678                         if (r_glsl_permutation->loc_FogColor >= 0)
2679                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2680                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2681                 }
2682                 else
2683                 {
2684                         if (mode == SHADERMODE_FLATCOLOR)
2685                         {
2686                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2687                         }
2688                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2689                         {
2690                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2691                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2692                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2693                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2694                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2695                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2696                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2697                         }
2698                         else
2699                         {
2700                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2701                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2702                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2703                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2704                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2705                         }
2706                         // additive passes are only darkened by fog, not tinted
2707                         if (r_glsl_permutation->loc_FogColor >= 0)
2708                         {
2709                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2710                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2711                                 else
2712                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2713                         }
2714                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2715                         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]);
2716                         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]);
2717                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2718                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2719                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2720                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2721                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2722                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2723                 }
2724                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2725                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2726                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2727                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2728                 {
2729                         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]);
2730                         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]);
2731                 }
2732                 else
2733                 {
2734                         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]);
2735                         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]);
2736                 }
2737
2738                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2739                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2740                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2741                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2742                 {
2743                         if (t->pantstexture)
2744                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2745                         else
2746                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2747                 }
2748                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2749                 {
2750                         if (t->shirttexture)
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2752                         else
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2754                 }
2755                 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]);
2756                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2757                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2758                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2759                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2760                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2761                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2762                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2763                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2764                         );
2765                 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);
2766                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2767                 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]);
2768                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2769                 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);}
2770                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2771
2772                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2773                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2774                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2775                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2776                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2777                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2778                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2779                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2780                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2781                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2782                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2783                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2784                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2785                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2786                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2787                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2788                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2789                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2790                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2791                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2792                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2793                 {
2794                         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);
2795                         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);
2796                         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);
2797                 }
2798                 else
2799                 {
2800                         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);
2801                 }
2802                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2803                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2804                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2805                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2806                 {
2807                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2808                         if (rsurface.rtlight)
2809                         {
2810                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2811                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2812                         }
2813                 }
2814                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2815                 CHECKGLERROR
2816                 break;
2817         case RENDERPATH_GL11:
2818         case RENDERPATH_GL13:
2819         case RENDERPATH_GLES1:
2820                 break;
2821         case RENDERPATH_SOFT:
2822                 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);
2823                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2824                 R_SetupShader_SetPermutationSoft(mode, permutation);
2825                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2826                 if (mode == SHADERMODE_LIGHTSOURCE)
2827                 {
2828                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2834         
2835                         // additive passes are only darkened by fog, not tinted
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2837                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2838                 }
2839                 else
2840                 {
2841                         if (mode == SHADERMODE_FLATCOLOR)
2842                         {
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2844                         }
2845                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2846                         {
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2852                         }
2853                         else
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2858                         }
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2861                         // additive passes are only darkened by fog, not tinted
2862                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         else
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2866                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2867                         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]);
2868                         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]);
2869                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2870                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2873                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2874                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2875                 }
2876                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2878                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2879                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2880                 {
2881                         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]);
2882                         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]);
2883                 }
2884                 else
2885                 {
2886                         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]);
2887                         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]);
2888                 }
2889
2890                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2891                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2892                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2893                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2894                 {
2895                         if (t->pantstexture)
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2897                         else
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2899                 }
2900                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2901                 {
2902                         if (t->shirttexture)
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2904                         else
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2906                 }
2907                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2910                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2911                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2912                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2913                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2914                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2915                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2916                         );
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2919                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2920                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2921
2922                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2923                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2924                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2925                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2928                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2929                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2930                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2931                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2932                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2933                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2934                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2935                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2936                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2937                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2938                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2939                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2940                 {
2941                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2942                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2943                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2944                 }
2945                 else
2946                 {
2947                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2948                 }
2949 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2951                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2952                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2953                 {
2954                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2955                         if (rsurface.rtlight)
2956                         {
2957                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2958                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2959                         }
2960                 }
2961                 break;
2962         }
2963 }
2964
2965 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2966 {
2967         // select a permutation of the lighting shader appropriate to this
2968         // combination of texture, entity, light source, and fogging, only use the
2969         // minimum features necessary to avoid wasting rendering time in the
2970         // fragment shader on features that are not being used
2971         dpuint64 permutation = 0;
2972         unsigned int mode = 0;
2973         const float *lightcolorbase = rtlight->currentcolor;
2974         float ambientscale = rtlight->ambientscale;
2975         float diffusescale = rtlight->diffusescale;
2976         float specularscale = rtlight->specularscale;
2977         // this is the location of the light in view space
2978         vec3_t viewlightorigin;
2979         // this transforms from view space (camera) to light space (cubemap)
2980         matrix4x4_t viewtolight;
2981         matrix4x4_t lighttoview;
2982         float viewtolight16f[16];
2983         // light source
2984         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2985         if (rtlight->currentcubemap != r_texture_whitecube)
2986                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2987         if (diffusescale > 0)
2988                 permutation |= SHADERPERMUTATION_DIFFUSE;
2989         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2990                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2991         if (r_shadow_usingshadowmap2d)
2992         {
2993                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2994                 if (r_shadow_shadowmapvsdct)
2995                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2996
2997                 if (r_shadow_shadowmap2ddepthbuffer)
2998                         permutation |= SHADERPERMUTATION_DEPTHRGB;
2999         }
3000         if (vid.allowalphatocoverage)
3001                 GL_AlphaToCoverage(false);
3002         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3003         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3004         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3005         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3006         switch(vid.renderpath)
3007         {
3008         case RENDERPATH_D3D9:
3009 #ifdef SUPPORTD3D
3010                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3011                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3012                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3013                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3014                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3015                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3016                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3017                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3018                 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);
3019                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3020                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3021
3022                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3023                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3024                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3025                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3026                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3027 #endif
3028                 break;
3029         case RENDERPATH_D3D10:
3030                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031                 break;
3032         case RENDERPATH_D3D11:
3033                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3034                 break;
3035         case RENDERPATH_GL20:
3036         case RENDERPATH_GLES2:
3037                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3038                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3039                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3040                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3041                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3042                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3043                 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]);
3044                 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]);
3045                 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);
3046                 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]);
3047                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3048
3049                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3050                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3051                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3052                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3053                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3054                 break;
3055         case RENDERPATH_GL11:
3056         case RENDERPATH_GL13:
3057         case RENDERPATH_GLES1:
3058                 break;
3059         case RENDERPATH_SOFT:
3060                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3063                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3064                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3065                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3066                 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]);
3067                 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]);
3068                 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);
3069                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3070                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3071
3072                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3073                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3074                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3075                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3076                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3077                 break;
3078         }
3079 }
3080
3081 #define SKINFRAME_HASH 1024
3082
3083 typedef struct
3084 {
3085         unsigned int loadsequence; // incremented each level change
3086         memexpandablearray_t array;
3087         skinframe_t *hash[SKINFRAME_HASH];
3088 }
3089 r_skinframe_t;
3090 r_skinframe_t r_skinframe;
3091
3092 void R_SkinFrame_PrepareForPurge(void)
3093 {
3094         r_skinframe.loadsequence++;
3095         // wrap it without hitting zero
3096         if (r_skinframe.loadsequence >= 200)
3097                 r_skinframe.loadsequence = 1;
3098 }
3099
3100 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3101 {
3102         if (!skinframe)
3103                 return;
3104         // mark the skinframe as used for the purging code
3105         skinframe->loadsequence = r_skinframe.loadsequence;
3106 }
3107
3108 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3109 {
3110         if (s->merged == s->base)
3111                 s->merged = NULL;
3112         R_PurgeTexture(s->stain); s->stain = NULL;
3113         R_PurgeTexture(s->merged); s->merged = NULL;
3114         R_PurgeTexture(s->base); s->base = NULL;
3115         R_PurgeTexture(s->pants); s->pants = NULL;
3116         R_PurgeTexture(s->shirt); s->shirt = NULL;
3117         R_PurgeTexture(s->nmap); s->nmap = NULL;
3118         R_PurgeTexture(s->gloss); s->gloss = NULL;
3119         R_PurgeTexture(s->glow); s->glow = NULL;
3120         R_PurgeTexture(s->fog); s->fog = NULL;
3121         R_PurgeTexture(s->reflect); s->reflect = NULL;
3122         s->loadsequence = 0;
3123 }
3124
3125 void R_SkinFrame_Purge(void)
3126 {
3127         int i;
3128         skinframe_t *s;
3129         for (i = 0;i < SKINFRAME_HASH;i++)
3130         {
3131                 for (s = r_skinframe.hash[i];s;s = s->next)
3132                 {
3133                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3134                                 R_SkinFrame_PurgeSkinFrame(s);
3135                 }
3136         }
3137 }
3138
3139 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3140         skinframe_t *item;
3141         char basename[MAX_QPATH];
3142
3143         Image_StripImageExtension(name, basename, sizeof(basename));
3144
3145         if( last == NULL ) {
3146                 int hashindex;
3147                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3148                 item = r_skinframe.hash[hashindex];
3149         } else {
3150                 item = last->next;
3151         }
3152
3153         // linearly search through the hash bucket
3154         for( ; item ; item = item->next ) {
3155                 if( !strcmp( item->basename, basename ) ) {
3156                         return item;
3157                 }
3158         }
3159         return NULL;
3160 }
3161
3162 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3163 {
3164         skinframe_t *item;
3165         int hashindex;
3166         char basename[MAX_QPATH];
3167
3168         Image_StripImageExtension(name, basename, sizeof(basename));
3169
3170         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3171         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3172                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3173                         break;
3174
3175         if (!item)
3176         {
3177                 if (!add)
3178                         return NULL;
3179                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3180                 memset(item, 0, sizeof(*item));
3181                 strlcpy(item->basename, basename, sizeof(item->basename));
3182                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3183                 item->comparewidth = comparewidth;
3184                 item->compareheight = compareheight;
3185                 item->comparecrc = comparecrc;
3186                 item->next = r_skinframe.hash[hashindex];
3187                 r_skinframe.hash[hashindex] = item;
3188         }
3189         else if (textureflags & TEXF_FORCE_RELOAD)
3190         {
3191                 if (!add)
3192                         return NULL;
3193                 R_SkinFrame_PurgeSkinFrame(item);
3194         }
3195
3196         R_SkinFrame_MarkUsed(item);
3197         return item;
3198 }
3199
3200 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3201         { \
3202                 unsigned long long avgcolor[5], wsum; \
3203                 int pix, comp, w; \
3204                 avgcolor[0] = 0; \
3205                 avgcolor[1] = 0; \
3206                 avgcolor[2] = 0; \
3207                 avgcolor[3] = 0; \
3208                 avgcolor[4] = 0; \
3209                 wsum = 0; \
3210                 for(pix = 0; pix < cnt; ++pix) \
3211                 { \
3212                         w = 0; \
3213                         for(comp = 0; comp < 3; ++comp) \
3214                                 w += getpixel; \
3215                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3216                         { \
3217                                 ++wsum; \
3218                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3219                                 w = getpixel; \
3220                                 for(comp = 0; comp < 3; ++comp) \
3221                                         avgcolor[comp] += getpixel * w; \
3222                                 avgcolor[3] += w; \
3223                         } \
3224                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3225                         avgcolor[4] += getpixel; \
3226                 } \
3227                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3228                         avgcolor[3] = 1; \
3229                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3230                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3231                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3232                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3233         }
3234
3235 extern cvar_t gl_picmip;
3236 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3237 {
3238         int j;
3239         unsigned char *pixels;
3240         unsigned char *bumppixels;
3241         unsigned char *basepixels = NULL;
3242         int basepixels_width = 0;
3243         int basepixels_height = 0;
3244         skinframe_t *skinframe;
3245         rtexture_t *ddsbase = NULL;
3246         qboolean ddshasalpha = false;
3247         float ddsavgcolor[4];
3248         char basename[MAX_QPATH];
3249         int miplevel = R_PicmipForFlags(textureflags);
3250         int savemiplevel = miplevel;
3251         int mymiplevel;
3252         char vabuf[1024];
3253
3254         if (cls.state == ca_dedicated)
3255                 return NULL;
3256
3257         // return an existing skinframe if already loaded
3258         // if loading of the first image fails, don't make a new skinframe as it
3259         // would cause all future lookups of this to be missing
3260         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3261         if (skinframe && skinframe->base)
3262                 return skinframe;
3263
3264         Image_StripImageExtension(name, basename, sizeof(basename));
3265
3266         // check for DDS texture file first
3267         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3268         {
3269                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3270                 if (basepixels == NULL && fallbacknotexture)
3271                         basepixels = Image_GenerateNoTexture();
3272                 if (basepixels == NULL)
3273                         return NULL;
3274         }
3275
3276         // FIXME handle miplevel
3277
3278         if (developer_loading.integer)
3279                 Con_Printf("loading skin \"%s\"\n", name);
3280
3281         // we've got some pixels to store, so really allocate this new texture now
3282         if (!skinframe)
3283                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3284         textureflags &= ~TEXF_FORCE_RELOAD;
3285         skinframe->stain = NULL;
3286         skinframe->merged = NULL;
3287         skinframe->base = NULL;
3288         skinframe->pants = NULL;
3289         skinframe->shirt = NULL;
3290         skinframe->nmap = NULL;
3291         skinframe->gloss = NULL;
3292         skinframe->glow = NULL;
3293         skinframe->fog = NULL;
3294         skinframe->reflect = NULL;
3295         skinframe->hasalpha = false;
3296         // we could store the q2animname here too
3297
3298         if (ddsbase)
3299         {
3300                 skinframe->base = ddsbase;
3301                 skinframe->hasalpha = ddshasalpha;
3302                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3303                 if (r_loadfog && skinframe->hasalpha)
3304                         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);
3305                 //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]);
3306         }
3307         else
3308         {
3309                 basepixels_width = image_width;
3310                 basepixels_height = image_height;
3311                 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);
3312                 if (textureflags & TEXF_ALPHA)
3313                 {
3314                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3315                         {
3316                                 if (basepixels[j] < 255)
3317                                 {
3318                                         skinframe->hasalpha = true;
3319                                         break;
3320                                 }
3321                         }
3322                         if (r_loadfog && skinframe->hasalpha)
3323                         {
3324                                 // has transparent pixels
3325                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3326                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3327                                 {
3328                                         pixels[j+0] = 255;
3329                                         pixels[j+1] = 255;
3330                                         pixels[j+2] = 255;
3331                                         pixels[j+3] = basepixels[j+3];
3332                                 }
3333                                 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);
3334                                 Mem_Free(pixels);
3335                         }
3336                 }
3337                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3338 #ifndef USE_GLES2
3339                 //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]);
3340                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3341                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3343                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3344 #endif
3345         }
3346
3347         if (r_loaddds)
3348         {
3349                 mymiplevel = savemiplevel;
3350                 if (r_loadnormalmap)
3351                         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);
3352                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3353                 if (r_loadgloss)
3354                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3355                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3356                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3357                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3358         }
3359
3360         // _norm is the name used by tenebrae and has been adopted as standard
3361         if (r_loadnormalmap && skinframe->nmap == NULL)
3362         {
3363                 mymiplevel = savemiplevel;
3364                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3365                 {
3366                         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);
3367                         Mem_Free(pixels);
3368                         pixels = NULL;
3369                 }
3370                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3371                 {
3372                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3373                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3374                         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);
3375                         Mem_Free(pixels);
3376                         Mem_Free(bumppixels);
3377                 }
3378                 else if (r_shadow_bumpscale_basetexture.value > 0)
3379                 {
3380                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3381                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3382                         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);
3383                         Mem_Free(pixels);
3384                 }
3385 #ifndef USE_GLES2
3386                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3387                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 #endif
3389         }
3390
3391         // _luma is supported only for tenebrae compatibility
3392         // _glow is the preferred name
3393         mymiplevel = savemiplevel;
3394         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))))
3395         {
3396                 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);
3397 #ifndef USE_GLES2
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3399                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3400 #endif
3401                 Mem_Free(pixels);pixels = NULL;
3402         }
3403
3404         mymiplevel = savemiplevel;
3405         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3406         {
3407                 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);
3408 #ifndef USE_GLES2
3409                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3410                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3411 #endif
3412                 Mem_Free(pixels);
3413                 pixels = NULL;
3414         }
3415
3416         mymiplevel = savemiplevel;
3417         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3418         {
3419                 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);
3420 #ifndef USE_GLES2
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3422                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3423 #endif
3424                 Mem_Free(pixels);
3425                 pixels = NULL;
3426         }
3427
3428         mymiplevel = savemiplevel;
3429         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3430         {
3431                 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);
3432 #ifndef USE_GLES2
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3434                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3435 #endif
3436                 Mem_Free(pixels);
3437                 pixels = NULL;
3438         }
3439
3440         mymiplevel = savemiplevel;
3441         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3442         {
3443                 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);
3444 #ifndef USE_GLES2
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3446                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 #endif
3448                 Mem_Free(pixels);
3449                 pixels = NULL;
3450         }
3451
3452         if (basepixels)
3453                 Mem_Free(basepixels);
3454
3455         return skinframe;
3456 }
3457
3458 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3459 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3460 {
3461         int i;
3462         skinframe_t *skinframe;
3463         char vabuf[1024];
3464
3465         if (cls.state == ca_dedicated)
3466                 return NULL;
3467
3468         // if already loaded just return it, otherwise make a new skinframe
3469         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3470         if (skinframe->base)
3471                 return skinframe;
3472         textureflags &= ~TEXF_FORCE_RELOAD;
3473
3474         skinframe->stain = NULL;
3475         skinframe->merged = NULL;
3476         skinframe->base = NULL;
3477         skinframe->pants = NULL;
3478         skinframe->shirt = NULL;
3479         skinframe->nmap = NULL;
3480         skinframe->gloss = NULL;
3481         skinframe->glow = NULL;
3482         skinframe->fog = NULL;
3483         skinframe->reflect = NULL;
3484         skinframe->hasalpha = false;
3485
3486         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3487         if (!skindata)
3488                 return NULL;
3489
3490         if (developer_loading.integer)
3491                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3492
3493         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3494         {
3495                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3496                 unsigned char *b = a + width * height * 4;
3497                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3498                 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);
3499                 Mem_Free(a);
3500         }
3501         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3502         if (textureflags & TEXF_ALPHA)
3503         {
3504                 for (i = 3;i < width * height * 4;i += 4)
3505                 {
3506                         if (skindata[i] < 255)
3507                         {
3508                                 skinframe->hasalpha = true;
3509                                 break;
3510                         }
3511                 }
3512                 if (r_loadfog && skinframe->hasalpha)
3513                 {
3514                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3515                         memcpy(fogpixels, skindata, width * height * 4);
3516                         for (i = 0;i < width * height * 4;i += 4)
3517                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3518                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3519                         Mem_Free(fogpixels);
3520                 }
3521         }
3522
3523         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3524         //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]);
3525
3526         return skinframe;
3527 }
3528
3529 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3530 {
3531         int i;
3532         int featuresmask;
3533         skinframe_t *skinframe;
3534
3535         if (cls.state == ca_dedicated)
3536                 return NULL;
3537
3538         // if already loaded just return it, otherwise make a new skinframe
3539         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3540         if (skinframe->base)
3541                 return skinframe;
3542         //textureflags &= ~TEXF_FORCE_RELOAD;
3543
3544         skinframe->stain = NULL;
3545         skinframe->merged = NULL;
3546         skinframe->base = NULL;
3547         skinframe->pants = NULL;
3548         skinframe->shirt = NULL;
3549         skinframe->nmap = NULL;
3550         skinframe->gloss = NULL;
3551         skinframe->glow = NULL;
3552         skinframe->fog = NULL;
3553         skinframe->reflect = NULL;
3554         skinframe->hasalpha = false;
3555
3556         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3557         if (!skindata)
3558                 return NULL;
3559
3560         if (developer_loading.integer)
3561                 Con_Printf("loading quake skin \"%s\"\n", name);
3562
3563         // 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)
3564         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3565         memcpy(skinframe->qpixels, skindata, width*height);
3566         skinframe->qwidth = width;
3567         skinframe->qheight = height;
3568
3569         featuresmask = 0;
3570         for (i = 0;i < width * height;i++)
3571                 featuresmask |= palette_featureflags[skindata[i]];
3572
3573         skinframe->hasalpha = false;
3574         // fence textures
3575         if (name[0] == '{')
3576                 skinframe->hasalpha = true;
3577         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3578         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3579         skinframe->qgeneratemerged = true;
3580         skinframe->qgeneratebase = skinframe->qhascolormapping;
3581         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3582
3583         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3584         //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]);
3585
3586         return skinframe;
3587 }
3588
3589 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3590 {
3591         int width;
3592         int height;
3593         unsigned char *skindata;
3594         char vabuf[1024];
3595
3596         if (!skinframe->qpixels)
3597                 return;
3598
3599         if (!skinframe->qhascolormapping)
3600                 colormapped = false;
3601
3602         if (colormapped)
3603         {
3604                 if (!skinframe->qgeneratebase)
3605                         return;
3606         }
3607         else
3608         {
3609                 if (!skinframe->qgeneratemerged)
3610                         return;
3611         }
3612
3613         width = skinframe->qwidth;
3614         height = skinframe->qheight;
3615         skindata = skinframe->qpixels;
3616
3617         if (skinframe->qgeneratenmap)
3618         {
3619                 unsigned char *a, *b;
3620                 skinframe->qgeneratenmap = false;
3621                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3622                 b = a + width * height * 4;
3623                 // use either a custom palette or the quake palette
3624                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3625                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3626                 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);
3627                 Mem_Free(a);
3628         }
3629
3630         if (skinframe->qgenerateglow)
3631         {
3632                 skinframe->qgenerateglow = false;
3633                 if (skinframe->hasalpha) // fence textures
3634                         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
3635                 else
3636                         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
3637         }
3638
3639         if (colormapped)
3640         {
3641                 skinframe->qgeneratebase = false;
3642                 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);
3643                 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);
3644                 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);
3645         }
3646         else
3647         {
3648                 skinframe->qgeneratemerged = false;
3649                 if (skinframe->hasalpha) // fence textures
3650                         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);
3651                 else
3652                         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);
3653         }
3654
3655         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3656         {
3657                 Mem_Free(skinframe->qpixels);
3658                 skinframe->qpixels = NULL;
3659         }
3660 }
3661
3662 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)
3663 {
3664         int i;
3665         skinframe_t *skinframe;
3666         char vabuf[1024];
3667
3668         if (cls.state == ca_dedicated)
3669                 return NULL;
3670
3671         // if already loaded just return it, otherwise make a new skinframe
3672         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3673         if (skinframe->base)
3674                 return skinframe;
3675         textureflags &= ~TEXF_FORCE_RELOAD;
3676
3677         skinframe->stain = NULL;
3678         skinframe->merged = NULL;
3679         skinframe->base = NULL;
3680         skinframe->pants = NULL;
3681         skinframe->shirt = NULL;
3682         skinframe->nmap = NULL;
3683         skinframe->gloss = NULL;
3684         skinframe->glow = NULL;
3685         skinframe->fog = NULL;
3686         skinframe->reflect = NULL;
3687         skinframe->hasalpha = false;
3688
3689         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3690         if (!skindata)
3691                 return NULL;
3692
3693         if (developer_loading.integer)
3694                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3695
3696         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3697         if ((textureflags & TEXF_ALPHA) && alphapalette)
3698         {
3699                 for (i = 0;i < width * height;i++)
3700                 {
3701                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3702                         {
3703                                 skinframe->hasalpha = true;
3704                                 break;
3705                         }
3706                 }
3707                 if (r_loadfog && skinframe->hasalpha)
3708                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3709         }
3710
3711         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3712         //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]);
3713
3714         return skinframe;
3715 }
3716
3717 skinframe_t *R_SkinFrame_LoadMissing(void)
3718 {
3719         skinframe_t *skinframe;
3720
3721         if (cls.state == ca_dedicated)
3722                 return NULL;
3723
3724         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3725         skinframe->stain = NULL;
3726         skinframe->merged = NULL;
3727         skinframe->base = NULL;
3728         skinframe->pants = NULL;
3729         skinframe->shirt = NULL;
3730         skinframe->nmap = NULL;
3731         skinframe->gloss = NULL;
3732         skinframe->glow = NULL;
3733         skinframe->fog = NULL;
3734         skinframe->reflect = NULL;
3735         skinframe->hasalpha = false;
3736
3737         skinframe->avgcolor[0] = rand() / RAND_MAX;
3738         skinframe->avgcolor[1] = rand() / RAND_MAX;
3739         skinframe->avgcolor[2] = rand() / RAND_MAX;
3740         skinframe->avgcolor[3] = 1;
3741
3742         return skinframe;
3743 }
3744
3745 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3746 {
3747         int x, y;
3748         static unsigned char pix[16][16][4];
3749
3750         if (cls.state == ca_dedicated)
3751                 return NULL;
3752
3753         // this makes a light grey/dark grey checkerboard texture
3754         if (!pix[0][0][3])
3755         {
3756                 for (y = 0; y < 16; y++)
3757                 {
3758                         for (x = 0; x < 16; x++)
3759                         {
3760                                 if ((y < 8) ^ (x < 8))
3761                                 {
3762                                         pix[y][x][0] = 128;
3763                                         pix[y][x][1] = 128;
3764                                         pix[y][x][2] = 128;
3765                                         pix[y][x][3] = 255;
3766                                 }
3767                                 else
3768                                 {
3769                                         pix[y][x][0] = 64;
3770                                         pix[y][x][1] = 64;
3771                                         pix[y][x][2] = 64;
3772                                         pix[y][x][3] = 255;
3773                                 }
3774                         }
3775                 }
3776         }
3777
3778         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3779 }
3780
3781 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3782 {
3783         skinframe_t *skinframe;
3784         if (cls.state == ca_dedicated)
3785                 return NULL;
3786         // if already loaded just return it, otherwise make a new skinframe
3787         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3788         if (skinframe->base)
3789                 return skinframe;
3790         textureflags &= ~TEXF_FORCE_RELOAD;
3791         skinframe->stain = NULL;
3792         skinframe->merged = NULL;
3793         skinframe->base = NULL;
3794         skinframe->pants = NULL;
3795         skinframe->shirt = NULL;
3796         skinframe->nmap = NULL;
3797         skinframe->gloss = NULL;
3798         skinframe->glow = NULL;
3799         skinframe->fog = NULL;
3800         skinframe->reflect = NULL;
3801         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3802         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3803         if (!tex)
3804                 return NULL;
3805         if (developer_loading.integer)
3806                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3807         skinframe->base = skinframe->merged = tex;
3808         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3809         return skinframe;
3810 }
3811
3812 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3813 typedef struct suffixinfo_s
3814 {
3815         const char *suffix;
3816         qboolean flipx, flipy, flipdiagonal;
3817 }
3818 suffixinfo_t;
3819 static suffixinfo_t suffix[3][6] =
3820 {
3821         {
3822                 {"px",   false, false, false},
3823                 {"nx",   false, false, false},
3824                 {"py",   false, false, false},
3825                 {"ny",   false, false, false},
3826                 {"pz",   false, false, false},
3827                 {"nz",   false, false, false}
3828         },
3829         {
3830                 {"posx", false, false, false},
3831                 {"negx", false, false, false},
3832                 {"posy", false, false, false},
3833                 {"negy", false, false, false},
3834                 {"posz", false, false, false},
3835                 {"negz", false, false, false}
3836         },
3837         {
3838                 {"rt",    true, false,  true},
3839                 {"lf",   false,  true,  true},
3840                 {"ft",    true,  true, false},
3841                 {"bk",   false, false, false},
3842                 {"up",    true, false,  true},
3843                 {"dn",    true, false,  true}
3844         }
3845 };
3846
3847 static int componentorder[4] = {0, 1, 2, 3};
3848
3849 static rtexture_t *R_LoadCubemap(const char *basename)
3850 {
3851         int i, j, cubemapsize;
3852         unsigned char *cubemappixels, *image_buffer;
3853         rtexture_t *cubemaptexture;
3854         char name[256];
3855         // must start 0 so the first loadimagepixels has no requested width/height
3856         cubemapsize = 0;
3857         cubemappixels = NULL;
3858         cubemaptexture = NULL;
3859         // keep trying different suffix groups (posx, px, rt) until one loads
3860         for (j = 0;j < 3 && !cubemappixels;j++)
3861         {
3862                 // load the 6 images in the suffix group
3863                 for (i = 0;i < 6;i++)
3864                 {
3865                         // generate an image name based on the base and and suffix
3866                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3867                         // load it
3868                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3869                         {
3870                                 // an image loaded, make sure width and height are equal
3871                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3872                                 {
3873                                         // if this is the first image to load successfully, allocate the cubemap memory
3874                                         if (!cubemappixels && image_width >= 1)
3875                                         {
3876                                                 cubemapsize = image_width;
3877                                                 // note this clears to black, so unavailable sides are black
3878                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3879                                         }
3880                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3881                                         if (cubemappixels)
3882                                                 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);
3883                                 }
3884                                 else
3885                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3886                                 // free the image
3887                                 Mem_Free(image_buffer);
3888                         }
3889                 }
3890         }
3891         // if a cubemap loaded, upload it
3892         if (cubemappixels)
3893         {
3894                 if (developer_loading.integer)
3895                         Con_Printf("loading cubemap \"%s\"\n", basename);
3896
3897                 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);
3898                 Mem_Free(cubemappixels);
3899         }
3900         else
3901         {
3902                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3903                 if (developer_loading.integer)
3904                 {
3905                         Con_Printf("(tried tried images ");
3906                         for (j = 0;j < 3;j++)
3907                                 for (i = 0;i < 6;i++)
3908                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3909                         Con_Print(" and was unable to find any of them).\n");
3910                 }
3911         }
3912         return cubemaptexture;
3913 }
3914
3915 rtexture_t *R_GetCubemap(const char *basename)
3916 {
3917         int i;
3918         for (i = 0;i < r_texture_numcubemaps;i++)
3919                 if (r_texture_cubemaps[i] != NULL)
3920                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3921                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3922         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3923                 return r_texture_whitecube;
3924         r_texture_numcubemaps++;
3925         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3926         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3927         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3928         return r_texture_cubemaps[i]->texture;
3929 }
3930
3931 static void R_Main_FreeViewCache(void)
3932 {
3933         if (r_refdef.viewcache.entityvisible)
3934                 Mem_Free(r_refdef.viewcache.entityvisible);
3935         if (r_refdef.viewcache.world_pvsbits)
3936                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3937         if (r_refdef.viewcache.world_leafvisible)
3938                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3939         if (r_refdef.viewcache.world_surfacevisible)
3940                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3941         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3942 }
3943
3944 static void R_Main_ResizeViewCache(void)
3945 {
3946         int numentities = r_refdef.scene.numentities;
3947         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3948         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3949         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3950         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3951         if (r_refdef.viewcache.maxentities < numentities)
3952         {
3953                 r_refdef.viewcache.maxentities = numentities;
3954                 if (r_refdef.viewcache.entityvisible)
3955                         Mem_Free(r_refdef.viewcache.entityvisible);
3956                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3957         }
3958         if (r_refdef.viewcache.world_numclusters != numclusters)
3959         {
3960                 r_refdef.viewcache.world_numclusters = numclusters;
3961                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3962                 if (r_refdef.viewcache.world_pvsbits)
3963                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3964                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3965         }
3966         if (r_refdef.viewcache.world_numleafs != numleafs)
3967         {
3968                 r_refdef.viewcache.world_numleafs = numleafs;
3969                 if (r_refdef.viewcache.world_leafvisible)
3970                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3971                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3972         }
3973         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3974         {
3975                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3976                 if (r_refdef.viewcache.world_surfacevisible)
3977                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3978                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3979         }
3980 }
3981
3982 extern rtexture_t *loadingscreentexture;
3983 static void gl_main_start(void)
3984 {
3985         loadingscreentexture = NULL;
3986         r_texture_blanknormalmap = NULL;
3987         r_texture_white = NULL;
3988         r_texture_grey128 = NULL;
3989         r_texture_black = NULL;
3990         r_texture_whitecube = NULL;
3991         r_texture_normalizationcube = NULL;
3992         r_texture_fogattenuation = NULL;
3993         r_texture_fogheighttexture = NULL;
3994         r_texture_gammaramps = NULL;
3995         r_texture_numcubemaps = 0;
3996         r_uniformbufferalignment = 32;
3997
3998         r_loaddds = r_texture_dds_load.integer != 0;
3999         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4000
4001         switch(vid.renderpath)
4002         {
4003         case RENDERPATH_GL20:
4004         case RENDERPATH_D3D9:
4005         case RENDERPATH_D3D10:
4006         case RENDERPATH_D3D11:
4007         case RENDERPATH_SOFT:
4008         case RENDERPATH_GLES2:
4009                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4010                 Cvar_SetValueQuick(&gl_combine, 1);
4011                 Cvar_SetValueQuick(&r_glsl, 1);
4012                 r_loadnormalmap = true;
4013                 r_loadgloss = true;
4014                 r_loadfog = false;
4015 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4016                 if (vid.support.arb_uniform_buffer_object)
4017                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4018 #endif
4019                         break;
4020         case RENDERPATH_GL13:
4021         case RENDERPATH_GLES1:
4022                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4023                 Cvar_SetValueQuick(&gl_combine, 1);
4024                 Cvar_SetValueQuick(&r_glsl, 0);
4025                 r_loadnormalmap = false;
4026                 r_loadgloss = false;
4027                 r_loadfog = true;
4028                 break;
4029         case RENDERPATH_GL11:
4030                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4031                 Cvar_SetValueQuick(&gl_combine, 0);
4032                 Cvar_SetValueQuick(&r_glsl, 0);
4033                 r_loadnormalmap = false;
4034                 r_loadgloss = false;
4035                 r_loadfog = true;
4036                 break;
4037         }
4038
4039         R_AnimCache_Free();
4040         R_FrameData_Reset();
4041         R_BufferData_Reset();
4042
4043         r_numqueries = 0;
4044         r_maxqueries = 0;
4045         memset(r_queries, 0, sizeof(r_queries));
4046
4047         r_qwskincache = NULL;
4048         r_qwskincache_size = 0;
4049
4050         // due to caching of texture_t references, the collision cache must be reset
4051         Collision_Cache_Reset(true);
4052
4053         // set up r_skinframe loading system for textures
4054         memset(&r_skinframe, 0, sizeof(r_skinframe));
4055         r_skinframe.loadsequence = 1;
4056         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4057
4058         r_main_texturepool = R_AllocTexturePool();
4059         R_BuildBlankTextures();
4060         R_BuildNoTexture();
4061         if (vid.support.arb_texture_cube_map)
4062         {
4063                 R_BuildWhiteCube();
4064                 R_BuildNormalizationCube();
4065         }
4066         r_texture_fogattenuation = NULL;
4067         r_texture_fogheighttexture = NULL;
4068         r_texture_gammaramps = NULL;
4069         //r_texture_fogintensity = NULL;
4070         memset(&r_fb, 0, sizeof(r_fb));
4071         r_glsl_permutation = NULL;
4072         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4073         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4074 #ifdef SUPPORTD3D
4075         r_hlsl_permutation = NULL;
4076         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4077         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4078 #endif
4079         memset(&r_svbsp, 0, sizeof (r_svbsp));
4080
4081         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4082         r_texture_numcubemaps = 0;
4083
4084         r_refdef.fogmasktable_density = 0;
4085
4086 #ifdef __ANDROID__
4087         // For Steelstorm Android
4088         // FIXME CACHE the program and reload
4089         // FIXME see possible combinations for SS:BR android
4090         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4091         R_SetupShader_SetPermutationGLSL(0, 12);
4092         R_SetupShader_SetPermutationGLSL(0, 13);
4093         R_SetupShader_SetPermutationGLSL(0, 8388621);
4094         R_SetupShader_SetPermutationGLSL(3, 0);
4095         R_SetupShader_SetPermutationGLSL(3, 2048);
4096         R_SetupShader_SetPermutationGLSL(5, 0);
4097         R_SetupShader_SetPermutationGLSL(5, 2);
4098         R_SetupShader_SetPermutationGLSL(5, 2048);
4099         R_SetupShader_SetPermutationGLSL(5, 8388608);
4100         R_SetupShader_SetPermutationGLSL(11, 1);
4101         R_SetupShader_SetPermutationGLSL(11, 2049);
4102         R_SetupShader_SetPermutationGLSL(11, 8193);
4103         R_SetupShader_SetPermutationGLSL(11, 10241);
4104         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4105 #endif
4106 }
4107
4108 static void gl_main_shutdown(void)
4109 {
4110         R_AnimCache_Free();
4111         R_FrameData_Reset();
4112         R_BufferData_Reset();
4113
4114         R_Main_FreeViewCache();
4115
4116         switch(vid.renderpath)
4117         {
4118         case RENDERPATH_GL11:
4119         case RENDERPATH_GL13:
4120         case RENDERPATH_GL20:
4121         case RENDERPATH_GLES1:
4122         case RENDERPATH_GLES2:
4123 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4124                 if (r_maxqueries)
4125                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4126 #endif
4127                 break;
4128         case RENDERPATH_D3D9:
4129                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4130                 break;
4131         case RENDERPATH_D3D10:
4132                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4133                 break;
4134         case RENDERPATH_D3D11:
4135                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4136                 break;
4137         case RENDERPATH_SOFT:
4138                 break;
4139         }
4140
4141         r_numqueries = 0;
4142         r_maxqueries = 0;
4143         memset(r_queries, 0, sizeof(r_queries));
4144
4145         r_qwskincache = NULL;
4146         r_qwskincache_size = 0;
4147
4148         // clear out the r_skinframe state
4149         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4150         memset(&r_skinframe, 0, sizeof(r_skinframe));
4151
4152         if (r_svbsp.nodes)
4153                 Mem_Free(r_svbsp.nodes);
4154         memset(&r_svbsp, 0, sizeof (r_svbsp));
4155         R_FreeTexturePool(&r_main_texturepool);
4156         loadingscreentexture = NULL;
4157         r_texture_blanknormalmap = NULL;
4158         r_texture_white = NULL;
4159         r_texture_grey128 = NULL;
4160         r_texture_black = NULL;
4161         r_texture_whitecube = NULL;
4162         r_texture_normalizationcube = NULL;
4163         r_texture_fogattenuation = NULL;
4164         r_texture_fogheighttexture = NULL;
4165         r_texture_gammaramps = NULL;
4166         r_texture_numcubemaps = 0;
4167         //r_texture_fogintensity = NULL;
4168         memset(&r_fb, 0, sizeof(r_fb));
4169         R_GLSL_Restart_f();
4170
4171         r_glsl_permutation = NULL;
4172         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4173         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4174 #ifdef SUPPORTD3D
4175         r_hlsl_permutation = NULL;
4176         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4177         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4178 #endif
4179 }
4180
4181 static void gl_main_newmap(void)
4182 {
4183         // FIXME: move this code to client
4184         char *entities, entname[MAX_QPATH];
4185         if (r_qwskincache)
4186                 Mem_Free(r_qwskincache);
4187         r_qwskincache = NULL;
4188         r_qwskincache_size = 0;
4189         if (cl.worldmodel)
4190         {
4191                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4192                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4193                 {
4194                         CL_ParseEntityLump(entities);
4195                         Mem_Free(entities);
4196                         return;
4197                 }
4198                 if (cl.worldmodel->brush.entities)
4199                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4200         }
4201         R_Main_FreeViewCache();
4202
4203         R_FrameData_Reset();
4204         R_BufferData_Reset();
4205 }
4206
4207 void GL_Main_Init(void)
4208 {
4209         int i;
4210         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4211         R_InitShaderModeInfo();
4212
4213         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4214         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4215         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4216         if (gamemode == GAME_NEHAHRA)
4217         {
4218                 Cvar_RegisterVariable (&gl_fogenable);
4219                 Cvar_RegisterVariable (&gl_fogdensity);
4220                 Cvar_RegisterVariable (&gl_fogred);
4221                 Cvar_RegisterVariable (&gl_foggreen);
4222                 Cvar_RegisterVariable (&gl_fogblue);
4223                 Cvar_RegisterVariable (&gl_fogstart);
4224                 Cvar_RegisterVariable (&gl_fogend);
4225                 Cvar_RegisterVariable (&gl_skyclip);
4226         }
4227         Cvar_RegisterVariable(&r_motionblur);
4228         Cvar_RegisterVariable(&r_damageblur);
4229         Cvar_RegisterVariable(&r_motionblur_averaging);
4230         Cvar_RegisterVariable(&r_motionblur_randomize);
4231         Cvar_RegisterVariable(&r_motionblur_minblur);
4232         Cvar_RegisterVariable(&r_motionblur_maxblur);
4233         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4234         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4235         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4236         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4237         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4238         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4239         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4240         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4241         Cvar_RegisterVariable(&r_equalize_entities_by);
4242         Cvar_RegisterVariable(&r_equalize_entities_to);
4243         Cvar_RegisterVariable(&r_depthfirst);
4244         Cvar_RegisterVariable(&r_useinfinitefarclip);
4245         Cvar_RegisterVariable(&r_farclip_base);
4246         Cvar_RegisterVariable(&r_farclip_world);
4247         Cvar_RegisterVariable(&r_nearclip);
4248         Cvar_RegisterVariable(&r_deformvertexes);
4249         Cvar_RegisterVariable(&r_transparent);
4250         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4251         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4252         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4253         Cvar_RegisterVariable(&r_showoverdraw);
4254         Cvar_RegisterVariable(&r_showbboxes);
4255         Cvar_RegisterVariable(&r_showbboxes_client);
4256         Cvar_RegisterVariable(&r_showsurfaces);
4257         Cvar_RegisterVariable(&r_showtris);
4258         Cvar_RegisterVariable(&r_shownormals);
4259         Cvar_RegisterVariable(&r_showlighting);
4260         Cvar_RegisterVariable(&r_showshadowvolumes);
4261         Cvar_RegisterVariable(&r_showcollisionbrushes);
4262         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4263         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4264         Cvar_RegisterVariable(&r_showdisabledepthtest);
4265         Cvar_RegisterVariable(&r_drawportals);
4266         Cvar_RegisterVariable(&r_drawentities);
4267         Cvar_RegisterVariable(&r_draw2d);
4268         Cvar_RegisterVariable(&r_drawworld);
4269         Cvar_RegisterVariable(&r_cullentities_trace);
4270         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4271         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4272         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4273         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4274         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4275         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4276         Cvar_RegisterVariable(&r_sortentities);
4277         Cvar_RegisterVariable(&r_drawviewmodel);
4278         Cvar_RegisterVariable(&r_drawexteriormodel);
4279         Cvar_RegisterVariable(&r_speeds);
4280         Cvar_RegisterVariable(&r_fullbrights);
4281         Cvar_RegisterVariable(&r_wateralpha);
4282         Cvar_RegisterVariable(&r_dynamic);
4283         Cvar_RegisterVariable(&r_fakelight);
4284         Cvar_RegisterVariable(&r_fakelight_intensity);
4285         Cvar_RegisterVariable(&r_fullbright_directed);
4286         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4287         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4288         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4289         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4290         Cvar_RegisterVariable(&r_fullbright);
4291         Cvar_RegisterVariable(&r_shadows);
4292         Cvar_RegisterVariable(&r_shadows_darken);
4293         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4294         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4295         Cvar_RegisterVariable(&r_shadows_throwdistance);
4296         Cvar_RegisterVariable(&r_shadows_throwdirection);
4297         Cvar_RegisterVariable(&r_shadows_focus);
4298         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4299         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4300         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4301         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4302         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4303         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4304         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4305         Cvar_RegisterVariable(&r_fog_exp2);
4306         Cvar_RegisterVariable(&r_fog_clear);
4307         Cvar_RegisterVariable(&r_drawfog);
4308         Cvar_RegisterVariable(&r_transparentdepthmasking);
4309         Cvar_RegisterVariable(&r_transparent_sortmindist);
4310         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4311         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4312         Cvar_RegisterVariable(&r_texture_dds_load);
4313         Cvar_RegisterVariable(&r_texture_dds_save);
4314         Cvar_RegisterVariable(&r_textureunits);
4315         Cvar_RegisterVariable(&gl_combine);
4316         Cvar_RegisterVariable(&r_usedepthtextures);
4317         Cvar_RegisterVariable(&r_viewfbo);
4318         Cvar_RegisterVariable(&r_viewscale);
4319         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4320         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4321         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4322         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4323         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4324         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4325         Cvar_RegisterVariable(&r_glsl);
4326         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4327         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4328         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4329         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4330         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4331         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4332         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4333         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4334         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4335         Cvar_RegisterVariable(&r_glsl_postprocess);
4336         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4337         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4338         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4339         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4340         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4341         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4342         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4343         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4344         Cvar_RegisterVariable(&r_celshading);
4345         Cvar_RegisterVariable(&r_celoutlines);
4346
4347         Cvar_RegisterVariable(&r_water);
4348         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4349         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4350         Cvar_RegisterVariable(&r_water_clippingplanebias);
4351         Cvar_RegisterVariable(&r_water_refractdistort);
4352         Cvar_RegisterVariable(&r_water_reflectdistort);
4353         Cvar_RegisterVariable(&r_water_scissormode);
4354         Cvar_RegisterVariable(&r_water_lowquality);
4355         Cvar_RegisterVariable(&r_water_hideplayer);
4356         Cvar_RegisterVariable(&r_water_fbo);
4357
4358         Cvar_RegisterVariable(&r_lerpsprites);
4359         Cvar_RegisterVariable(&r_lerpmodels);
4360         Cvar_RegisterVariable(&r_lerplightstyles);
4361         Cvar_RegisterVariable(&r_waterscroll);
4362         Cvar_RegisterVariable(&r_bloom);
4363         Cvar_RegisterVariable(&r_bloom_colorscale);
4364         Cvar_RegisterVariable(&r_bloom_brighten);
4365         Cvar_RegisterVariable(&r_bloom_blur);
4366         Cvar_RegisterVariable(&r_bloom_resolution);
4367         Cvar_RegisterVariable(&r_bloom_colorexponent);
4368         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4369         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4370         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4371         Cvar_RegisterVariable(&r_hdr_glowintensity);
4372         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4373         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4374         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4375         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4376         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4377         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4378         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4379         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4380         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4381         Cvar_RegisterVariable(&developer_texturelogging);
4382         Cvar_RegisterVariable(&gl_lightmaps);
4383         Cvar_RegisterVariable(&r_test);
4384         Cvar_RegisterVariable(&r_batch_multidraw);
4385         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4386         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4387         Cvar_RegisterVariable(&r_glsl_skeletal);
4388         Cvar_RegisterVariable(&r_glsl_saturation);
4389         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4390         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4391         Cvar_RegisterVariable(&r_framedatasize);
4392         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4393                 Cvar_RegisterVariable(&r_buffermegs[i]);
4394         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4395         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4396                 Cvar_SetValue("r_fullbrights", 0);
4397 #ifdef DP_MOBILETOUCH
4398         // GLES devices have terrible depth precision in general, so...
4399         Cvar_SetValueQuick(&r_nearclip, 4);
4400         Cvar_SetValueQuick(&r_farclip_base, 4096);
4401         Cvar_SetValueQuick(&r_farclip_world, 0);
4402         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4403 #endif
4404         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4405 }
4406
4407 void Render_Init(void)
4408 {
4409         gl_backend_init();
4410         R_Textures_Init();
4411         GL_Main_Init();
4412         Font_Init();
4413         GL_Draw_Init();
4414         R_Shadow_Init();
4415         R_Sky_Init();
4416         GL_Surf_Init();
4417         Sbar_Init();
4418         R_Particles_Init();
4419         R_Explosion_Init();
4420         R_LightningBeams_Init();
4421         Mod_RenderInit();
4422 }
4423
4424 /*
4425 ===============
4426 GL_Init
4427 ===============
4428 */
4429 #ifndef USE_GLES2
4430 extern char *ENGINE_EXTENSIONS;
4431 void GL_Init (void)
4432 {
4433         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4434         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4435         gl_version = (const char *)qglGetString(GL_VERSION);
4436         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4437
4438         if (!gl_extensions)
4439                 gl_extensions = "";
4440         if (!gl_platformextensions)
4441                 gl_platformextensions = "";
4442
4443         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4444         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4445         Con_Printf("GL_VERSION: %s\n", gl_version);
4446         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4447         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4448
4449         VID_CheckExtensions();
4450
4451         // LordHavoc: report supported extensions
4452 #ifdef CONFIG_MENU
4453         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4454 #else
4455         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4456 #endif
4457
4458         // clear to black (loading plaque will be seen over this)
4459         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4460 }
4461 #endif
4462
4463 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4464 {
4465         int i;
4466         mplane_t *p;
4467         if (r_trippy.integer)
4468                 return false;
4469         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4470         {
4471                 p = r_refdef.view.frustum + i;
4472                 switch(p->signbits)
4473                 {
4474                 default:
4475                 case 0:
4476                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 1:
4480                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 2:
4484                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 3:
4488                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 case 4:
4492                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4493                                 return true;
4494                         break;
4495                 case 5:
4496                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 6:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 7:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 }
4508         }
4509         return false;
4510 }
4511
4512 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4513 {
4514         int i;
4515         const mplane_t *p;
4516         if (r_trippy.integer)
4517                 return false;
4518         for (i = 0;i < numplanes;i++)
4519         {
4520                 p = planes + i;
4521                 switch(p->signbits)
4522                 {
4523                 default:
4524                 case 0:
4525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4526                                 return true;
4527                         break;
4528                 case 1:
4529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4530                                 return true;
4531                         break;
4532                 case 2:
4533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4534                                 return true;
4535                         break;
4536                 case 3:
4537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4538                                 return true;
4539                         break;
4540                 case 4:
4541                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4542                                 return true;
4543                         break;
4544                 case 5:
4545                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4546                                 return true;
4547                         break;
4548                 case 6:
4549                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4550                                 return true;
4551                         break;
4552                 case 7:
4553                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 }
4557         }
4558         return false;
4559 }
4560
4561 //==================================================================================
4562
4563 // LordHavoc: this stores temporary data used within the same frame
4564
4565 typedef struct r_framedata_mem_s
4566 {
4567         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4568         size_t size; // how much usable space
4569         size_t current; // how much space in use
4570         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4571         size_t wantedsize; // how much space was allocated
4572         unsigned char *data; // start of real data (16byte aligned)
4573 }
4574 r_framedata_mem_t;
4575
4576 static r_framedata_mem_t *r_framedata_mem;
4577
4578 void R_FrameData_Reset(void)
4579 {
4580         while (r_framedata_mem)
4581         {
4582                 r_framedata_mem_t *next = r_framedata_mem->purge;
4583                 Mem_Free(r_framedata_mem);
4584                 r_framedata_mem = next;
4585         }
4586 }
4587
4588 static void R_FrameData_Resize(qboolean mustgrow)
4589 {
4590         size_t wantedsize;
4591         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4592         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4593         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4594         {
4595                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4596                 newmem->wantedsize = wantedsize;
4597                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4598                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4599                 newmem->current = 0;
4600                 newmem->mark = 0;
4601                 newmem->purge = r_framedata_mem;
4602                 r_framedata_mem = newmem;
4603         }
4604 }
4605
4606 void R_FrameData_NewFrame(void)
4607 {
4608         R_FrameData_Resize(false);
4609         if (!r_framedata_mem)
4610                 return;
4611         // if we ran out of space on the last frame, free the old memory now
4612         while (r_framedata_mem->purge)
4613         {
4614                 // repeatedly remove the second item in the list, leaving only head
4615                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4616                 Mem_Free(r_framedata_mem->purge);
4617                 r_framedata_mem->purge = next;
4618         }
4619         // reset the current mem pointer
4620         r_framedata_mem->current = 0;
4621         r_framedata_mem->mark = 0;
4622 }
4623
4624 void *R_FrameData_Alloc(size_t size)
4625 {
4626         void *data;
4627         float newvalue;
4628
4629         // align to 16 byte boundary - the data pointer is already aligned, so we
4630         // only need to ensure the size of every allocation is also aligned
4631         size = (size + 15) & ~15;
4632
4633         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4634         {
4635                 // emergency - we ran out of space, allocate more memory
4636                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4637                 newvalue = r_framedatasize.value * 2.0f;
4638                 // 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
4639                 if (sizeof(size_t) >= 8)
4640                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4641                 else
4642                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4643                 // this might not be a growing it, but we'll allocate another buffer every time
4644                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4645                 R_FrameData_Resize(true);
4646         }
4647
4648         data = r_framedata_mem->data + r_framedata_mem->current;
4649         r_framedata_mem->current += size;
4650
4651         // count the usage for stats
4652         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4653         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4654
4655         return (void *)data;
4656 }
4657
4658 void *R_FrameData_Store(size_t size, void *data)
4659 {
4660         void *d = R_FrameData_Alloc(size);
4661         if (d && data)
4662                 memcpy(d, data, size);
4663         return d;
4664 }
4665
4666 void R_FrameData_SetMark(void)
4667 {
4668         if (!r_framedata_mem)
4669                 return;
4670         r_framedata_mem->mark = r_framedata_mem->current;
4671 }
4672
4673 void R_FrameData_ReturnToMark(void)
4674 {
4675         if (!r_framedata_mem)
4676                 return;
4677         r_framedata_mem->current = r_framedata_mem->mark;
4678 }
4679
4680 //==================================================================================
4681
4682 // avoid reusing the same buffer objects on consecutive frames
4683 #define R_BUFFERDATA_CYCLE 3
4684
4685 typedef struct r_bufferdata_buffer_s
4686 {
4687         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4688         size_t size; // how much usable space
4689         size_t current; // how much space in use
4690         r_meshbuffer_t *buffer; // the buffer itself
4691 }
4692 r_bufferdata_buffer_t;
4693
4694 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4695 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4696
4697 /// frees all dynamic buffers
4698 void R_BufferData_Reset(void)
4699 {
4700         int cycle, type;
4701         r_bufferdata_buffer_t **p, *mem;
4702         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4703         {
4704                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4705                 {
4706                         // free all buffers
4707                         p = &r_bufferdata_buffer[cycle][type];
4708                         while (*p)
4709                         {
4710                                 mem = *p;
4711                                 *p = (*p)->purge;
4712                                 if (mem->buffer)
4713                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4714                                 Mem_Free(mem);
4715                         }
4716                 }
4717         }
4718 }
4719
4720 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4721 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4722 {
4723         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4724         size_t size;
4725         float newvalue = r_buffermegs[type].value;
4726
4727         // increase the cvar if we have to (but only if we already have a mem)
4728         if (mustgrow && mem)
4729                 newvalue *= 2.0f;
4730         newvalue = bound(0.25f, newvalue, 256.0f);
4731         while (newvalue * 1024*1024 < minsize)
4732                 newvalue *= 2.0f;
4733
4734         // clamp the cvar to valid range
4735         newvalue = bound(0.25f, newvalue, 256.0f);
4736         if (r_buffermegs[type].value != newvalue)
4737                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4738
4739         // calculate size in bytes
4740         size = (size_t)(newvalue * 1024*1024);
4741         size = bound(131072, size, 256*1024*1024);
4742
4743         // allocate a new buffer if the size is different (purge old one later)
4744         // or if we were told we must grow the buffer
4745         if (!mem || mem->size != size || mustgrow)
4746         {
4747                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4748                 mem->size = size;
4749                 mem->current = 0;
4750                 if (type == R_BUFFERDATA_VERTEX)
4751                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4752                 else if (type == R_BUFFERDATA_INDEX16)
4753                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4754                 else if (type == R_BUFFERDATA_INDEX32)
4755                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4756                 else if (type == R_BUFFERDATA_UNIFORM)
4757                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4758                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4759                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4760         }
4761 }
4762
4763 void R_BufferData_NewFrame(void)
4764 {
4765         int type;
4766         r_bufferdata_buffer_t **p, *mem;
4767         // cycle to the next frame's buffers
4768         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4769         // if we ran out of space on the last time we used these buffers, free the old memory now
4770         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4771         {
4772                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4773                 {
4774                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4775                         // free all but the head buffer, this is how we recycle obsolete
4776                         // buffers after they are no longer in use
4777                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4778                         while (*p)
4779                         {
4780                                 mem = *p;
4781                                 *p = (*p)->purge;
4782                                 if (mem->buffer)
4783                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4784                                 Mem_Free(mem);
4785                         }
4786                         // reset the current offset
4787                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4788                 }
4789         }
4790 }
4791
4792 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4793 {
4794         r_bufferdata_buffer_t *mem;
4795         int offset = 0;
4796         int padsize;
4797
4798         *returnbufferoffset = 0;
4799
4800         // align size to a byte boundary appropriate for the buffer type, this
4801         // makes all allocations have aligned start offsets
4802         if (type == R_BUFFERDATA_UNIFORM)
4803                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4804         else
4805                 padsize = (datasize + 15) & ~15;
4806
4807         // if we ran out of space in this buffer we must allocate a new one
4808         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)
4809                 R_BufferData_Resize(type, true, padsize);
4810
4811         // if the resize did not give us enough memory, fail
4812         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)
4813                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4814
4815         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4816         offset = (int)mem->current;
4817         mem->current += padsize;
4818
4819         // upload the data to the buffer at the chosen offset
4820         if (offset == 0)
4821                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4822         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4823
4824         // count the usage for stats
4825         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4826         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4827
4828         // return the buffer offset
4829         *returnbufferoffset = offset;
4830
4831         return mem->buffer;
4832 }
4833
4834 //==================================================================================
4835
4836 // LordHavoc: animcache originally written by Echon, rewritten since then
4837
4838 /**
4839  * Animation cache prevents re-generating mesh data for an animated model
4840  * multiple times in one frame for lighting, shadowing, reflections, etc.
4841  */
4842
4843 void R_AnimCache_Free(void)
4844 {
4845 }
4846
4847 void R_AnimCache_ClearCache(void)
4848 {
4849         int i;
4850         entity_render_t *ent;
4851
4852         for (i = 0;i < r_refdef.scene.numentities;i++)
4853         {
4854                 ent = r_refdef.scene.entities[i];
4855                 ent->animcache_vertex3f = NULL;
4856                 ent->animcache_vertex3f_vertexbuffer = NULL;
4857                 ent->animcache_vertex3f_bufferoffset = 0;
4858                 ent->animcache_normal3f = NULL;
4859                 ent->animcache_normal3f_vertexbuffer = NULL;
4860                 ent->animcache_normal3f_bufferoffset = 0;
4861                 ent->animcache_svector3f = NULL;
4862                 ent->animcache_svector3f_vertexbuffer = NULL;
4863                 ent->animcache_svector3f_bufferoffset = 0;
4864                 ent->animcache_tvector3f = NULL;
4865                 ent->animcache_tvector3f_vertexbuffer = NULL;
4866                 ent->animcache_tvector3f_bufferoffset = 0;
4867                 ent->animcache_vertexmesh = NULL;
4868                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4869                 ent->animcache_vertexmesh_bufferoffset = 0;
4870                 ent->animcache_skeletaltransform3x4 = NULL;
4871                 ent->animcache_skeletaltransform3x4buffer = NULL;
4872                 ent->animcache_skeletaltransform3x4offset = 0;
4873                 ent->animcache_skeletaltransform3x4size = 0;
4874         }
4875 }
4876
4877 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4878 {
4879         int i;
4880
4881         // check if we need the meshbuffers
4882         if (!vid.useinterleavedarrays)
4883                 return;
4884
4885         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4886                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4887         // TODO: upload vertexbuffer?
4888         if (ent->animcache_vertexmesh)
4889         {
4890                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4891                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4892                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4893                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4894                 for (i = 0;i < numvertices;i++)
4895                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4896                 if (ent->animcache_svector3f)
4897                         for (i = 0;i < numvertices;i++)
4898                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4899                 if (ent->animcache_tvector3f)
4900                         for (i = 0;i < numvertices;i++)
4901                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4902                 if (ent->animcache_normal3f)
4903                         for (i = 0;i < numvertices;i++)
4904                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4905         }
4906 }
4907
4908 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4909 {
4910         dp_model_t *model = ent->model;
4911         int numvertices;
4912
4913         // see if this ent is worth caching
4914         if (!model || !model->Draw || !model->AnimateVertices)
4915                 return false;
4916         // nothing to cache if it contains no animations and has no skeleton
4917         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4918                 return false;
4919         // see if it is already cached for gpuskeletal
4920         if (ent->animcache_skeletaltransform3x4)
4921                 return false;
4922         // see if it is already cached as a mesh
4923         if (ent->animcache_vertex3f)
4924         {
4925                 // check if we need to add normals or tangents
4926                 if (ent->animcache_normal3f)
4927                         wantnormals = false;
4928                 if (ent->animcache_svector3f)
4929                         wanttangents = false;
4930                 if (!wantnormals && !wanttangents)
4931                         return false;
4932         }
4933
4934         // check which kind of cache we need to generate
4935         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4936         {
4937                 // cache the skeleton so the vertex shader can use it
4938                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4939                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4940                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4941                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4942                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4943                 // note: this can fail if the buffer is at the grow limit
4944                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4945                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4946         }
4947         else if (ent->animcache_vertex3f)
4948         {
4949                 // mesh was already cached but we may need to add normals/tangents
4950                 // (this only happens with multiple views, reflections, cameras, etc)
4951                 if (wantnormals || wanttangents)
4952                 {
4953                         numvertices = model->surfmesh.num_vertices;
4954                         if (wantnormals)
4955                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4956                         if (wanttangents)
4957                         {
4958                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4959                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4960                         }
4961                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4962                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4963                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4964                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4965                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4966                 }
4967         }
4968         else
4969         {
4970                 // generate mesh cache
4971                 numvertices = model->surfmesh.num_vertices;
4972                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973                 if (wantnormals)
4974                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4975                 if (wanttangents)
4976                 {
4977                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979                 }
4980                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4981                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4982                 if (wantnormals || wanttangents)
4983                 {
4984                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4985                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4986                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4987                 }
4988                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4989                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4990                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4991         }
4992         return true;
4993 }
4994
4995 void R_AnimCache_CacheVisibleEntities(void)
4996 {
4997         int i;
4998         qboolean wantnormals = true;
4999         qboolean wanttangents = !r_showsurfaces.integer;
5000
5001         switch(vid.renderpath)
5002         {
5003         case RENDERPATH_GL20:
5004         case RENDERPATH_D3D9:
5005         case RENDERPATH_D3D10:
5006         case RENDERPATH_D3D11:
5007         case RENDERPATH_GLES2:
5008                 break;
5009         case RENDERPATH_GL11:
5010         case RENDERPATH_GL13:
5011         case RENDERPATH_GLES1:
5012                 wanttangents = false;
5013                 break;
5014         case RENDERPATH_SOFT:
5015                 break;
5016         }
5017
5018         if (r_shownormals.integer)
5019                 wanttangents = wantnormals = true;
5020
5021         // TODO: thread this
5022         // NOTE: R_PrepareRTLights() also caches entities
5023
5024         for (i = 0;i < r_refdef.scene.numentities;i++)
5025                 if (r_refdef.viewcache.entityvisible[i])
5026                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5027 }
5028
5029 //==================================================================================
5030
5031 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5032 {
5033         int i;
5034         vec3_t eyemins, eyemaxs;
5035         vec3_t boxmins, boxmaxs;
5036         vec3_t start;
5037         vec3_t end;
5038         dp_model_t *model = r_refdef.scene.worldmodel;
5039         static vec3_t positions[] = {
5040                 { 0.5f, 0.5f, 0.5f },
5041                 { 0.0f, 0.0f, 0.0f },
5042                 { 0.0f, 0.0f, 1.0f },
5043                 { 0.0f, 1.0f, 0.0f },
5044                 { 0.0f, 1.0f, 1.0f },
5045                 { 1.0f, 0.0f, 0.0f },
5046                 { 1.0f, 0.0f, 1.0f },
5047                 { 1.0f, 1.0f, 0.0f },
5048                 { 1.0f, 1.0f, 1.0f },
5049         };
5050
5051         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5052         if (numsamples < 0)
5053                 return true;
5054
5055         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5056         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5057                 return true;
5058
5059         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5060                 return true;
5061
5062         // expand the eye box a little
5063         eyemins[0] = eye[0] - eyejitter;
5064         eyemaxs[0] = eye[0] + eyejitter;
5065         eyemins[1] = eye[1] - eyejitter;
5066         eyemaxs[1] = eye[1] + eyejitter;
5067         eyemins[2] = eye[2] - eyejitter;
5068         eyemaxs[2] = eye[2] + eyejitter;
5069         // expand the box a little
5070         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5071         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5072         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5073         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5074         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5075         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5076
5077         // return true if eye overlaps enlarged box
5078         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5079                 return true;
5080
5081         // try specific positions in the box first - note that these can be cached
5082         if (r_cullentities_trace_entityocclusion.integer)
5083         {
5084                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5085                 {
5086                         VectorCopy(eye, start);
5087                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5088                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5089                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5090                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5091                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5092                         // not picky - if the trace ended anywhere in the box we're good
5093                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5094                                 return true;
5095                 }
5096         }
5097         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5098                 return true;
5099
5100         // try various random positions
5101         for (i = 0; i < numsamples; i++)
5102         {
5103                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5104                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5105                 if (r_cullentities_trace_entityocclusion.integer)
5106                 {
5107                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5108                         // not picky - if the trace ended anywhere in the box we're good
5109                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5110                                 return true;
5111                 }
5112                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5113                         return true;
5114         }
5115
5116         return false;
5117 }
5118
5119
5120 static void R_View_UpdateEntityVisible (void)
5121 {
5122         int i;
5123         int renderimask;
5124         int samples;
5125         entity_render_t *ent;
5126
5127         if (r_refdef.envmap || r_fb.water.hideplayer)
5128                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5129         else if (chase_active.integer || r_fb.water.renderingscene)
5130                 renderimask = RENDER_VIEWMODEL;
5131         else
5132                 renderimask = RENDER_EXTERIORMODEL;
5133         if (!r_drawviewmodel.integer)
5134                 renderimask |= RENDER_VIEWMODEL;
5135         if (!r_drawexteriormodel.integer)
5136                 renderimask |= RENDER_EXTERIORMODEL;
5137         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5138         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5139         {
5140                 // worldmodel can check visibility
5141                 for (i = 0;i < r_refdef.scene.numentities;i++)
5142                 {
5143                         ent = r_refdef.scene.entities[i];
5144                         if (!(ent->flags & renderimask))
5145                         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)))
5146                         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))
5147                                 r_refdef.viewcache.entityvisible[i] = true;
5148                 }
5149         }
5150         else
5151         {
5152                 // no worldmodel or it can't check visibility
5153                 for (i = 0;i < r_refdef.scene.numentities;i++)
5154                 {
5155                         ent = r_refdef.scene.entities[i];
5156                         if (!(ent->flags & renderimask))
5157                         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)))
5158                                 r_refdef.viewcache.entityvisible[i] = true;
5159                 }
5160         }
5161         if (r_cullentities_trace.integer)
5162         {
5163                 for (i = 0;i < r_refdef.scene.numentities;i++)
5164                 {
5165                         if (!r_refdef.viewcache.entityvisible[i])
5166                                 continue;
5167                         ent = r_refdef.scene.entities[i];
5168                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5169                         {
5170                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5171                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5172                                         ent->last_trace_visibility = realtime;
5173                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5174                                         r_refdef.viewcache.entityvisible[i] = 0;
5175                         }
5176                 }
5177         }
5178 }
5179
5180 /// only used if skyrendermasked, and normally returns false
5181 static int R_DrawBrushModelsSky (void)
5182 {
5183         int i, sky;
5184         entity_render_t *ent;
5185
5186         sky = false;
5187         for (i = 0;i < r_refdef.scene.numentities;i++)
5188         {
5189                 if (!r_refdef.viewcache.entityvisible[i])
5190                         continue;
5191                 ent = r_refdef.scene.entities[i];
5192                 if (!ent->model || !ent->model->DrawSky)
5193                         continue;
5194                 ent->model->DrawSky(ent);
5195                 sky = true;
5196         }
5197         return sky;
5198 }
5199
5200 static void R_DrawNoModel(entity_render_t *ent);
5201 static void R_DrawModels(void)
5202 {
5203         int i;
5204         entity_render_t *ent;
5205
5206         for (i = 0;i < r_refdef.scene.numentities;i++)
5207         {
5208                 if (!r_refdef.viewcache.entityvisible[i])
5209                         continue;
5210                 ent = r_refdef.scene.entities[i];
5211                 r_refdef.stats[r_stat_entities]++;
5212                 /*
5213                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5214                 {
5215                         vec3_t f, l, u, o;
5216                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5217                         Con_Printf("R_DrawModels\n");
5218                         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]);
5219                         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);
5220                         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);
5221                 }
5222                 */
5223                 if (ent->model && ent->model->Draw != NULL)
5224                         ent->model->Draw(ent);
5225                 else
5226                         R_DrawNoModel(ent);
5227         }
5228 }
5229
5230 static void R_DrawModelsDepth(void)
5231 {
5232         int i;
5233         entity_render_t *ent;
5234
5235         for (i = 0;i < r_refdef.scene.numentities;i++)
5236         {
5237                 if (!r_refdef.viewcache.entityvisible[i])
5238                         continue;
5239                 ent = r_refdef.scene.entities[i];
5240                 if (ent->model && ent->model->DrawDepth != NULL)
5241                         ent->model->DrawDepth(ent);
5242         }
5243 }
5244
5245 static void R_DrawModelsDebug(void)
5246 {
5247         int i;
5248         entity_render_t *ent;
5249
5250         for (i = 0;i < r_refdef.scene.numentities;i++)
5251         {
5252                 if (!r_refdef.viewcache.entityvisible[i])
5253                         continue;
5254                 ent = r_refdef.scene.entities[i];
5255                 if (ent->model && ent->model->DrawDebug != NULL)
5256                         ent->model->DrawDebug(ent);
5257         }
5258 }
5259
5260 static void R_DrawModelsAddWaterPlanes(void)
5261 {
5262         int i;
5263         entity_render_t *ent;
5264
5265         for (i = 0;i < r_refdef.scene.numentities;i++)
5266         {
5267                 if (!r_refdef.viewcache.entityvisible[i])
5268                         continue;
5269                 ent = r_refdef.scene.entities[i];
5270                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5271                         ent->model->DrawAddWaterPlanes(ent);
5272         }
5273 }
5274
5275 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}};
5276
5277 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5278 {
5279         if (r_hdr_irisadaptation.integer)
5280         {
5281                 vec3_t p;
5282                 vec3_t ambient;
5283                 vec3_t diffuse;
5284                 vec3_t diffusenormal;
5285                 vec3_t forward;
5286                 vec_t brightness = 0.0f;
5287                 vec_t goal;
5288                 vec_t current;
5289                 vec_t d;
5290                 int c;
5291                 VectorCopy(r_refdef.view.forward, forward);
5292                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5293                 {
5294                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5295                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5296                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5297                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5298                         d = DotProduct(forward, diffusenormal);
5299                         brightness += VectorLength(ambient);
5300                         if (d > 0)
5301                                 brightness += d * VectorLength(diffuse);
5302                 }
5303                 brightness *= 1.0f / c;
5304                 brightness += 0.00001f; // make sure it's never zero
5305                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5306                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5307                 current = r_hdr_irisadaptation_value.value;
5308                 if (current < goal)
5309                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5310                 else if (current > goal)
5311                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5312                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5313                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5314         }
5315         else if (r_hdr_irisadaptation_value.value != 1.0f)
5316                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5317 }
5318
5319 static void R_View_SetFrustum(const int *scissor)
5320 {
5321         int i;
5322         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5323         vec3_t forward, left, up, origin, v;
5324
5325         if(scissor)
5326         {
5327                 // flipped x coordinates (because x points left here)
5328                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5329                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5330
5331                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5332                 switch(vid.renderpath)
5333                 {
5334                         case RENDERPATH_D3D9:
5335                         case RENDERPATH_D3D10:
5336                         case RENDERPATH_D3D11:
5337                                 // non-flipped y coordinates
5338                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5339                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5340                                 break;
5341                         case RENDERPATH_SOFT:
5342                         case RENDERPATH_GL11:
5343                         case RENDERPATH_GL13:
5344                         case RENDERPATH_GL20:
5345                         case RENDERPATH_GLES1:
5346                         case RENDERPATH_GLES2:
5347                                 // non-flipped y coordinates
5348                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5349                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5350                                 break;
5351                 }
5352         }
5353
5354         // we can't trust r_refdef.view.forward and friends in reflected scenes
5355         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5356
5357 #if 0
5358         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5359         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5360         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5361         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5362         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5363         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5364         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5365         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5366         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5367         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5368         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5369         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5370 #endif
5371
5372 #if 0
5373         zNear = r_refdef.nearclip;
5374         nudge = 1.0 - 1.0 / (1<<23);
5375         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5376         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5377         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5378         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5379         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5380         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5381         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5382         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5383 #endif
5384
5385
5386
5387 #if 0
5388         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5389         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5390         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5391         r_refdef.view.frustum[0].dist = m[15] - m[12];
5392
5393         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5394         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5395         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5396         r_refdef.view.frustum[1].dist = m[15] + m[12];
5397
5398         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5399         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5400         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5401         r_refdef.view.frustum[2].dist = m[15] - m[13];
5402
5403         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5404         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5405         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5406         r_refdef.view.frustum[3].dist = m[15] + m[13];
5407
5408         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5409         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5410         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5411         r_refdef.view.frustum[4].dist = m[15] - m[14];
5412
5413         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5414         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5415         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5416         r_refdef.view.frustum[5].dist = m[15] + m[14];
5417 #endif
5418
5419         if (r_refdef.view.useperspective)
5420         {
5421                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5422                 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]);
5423                 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]);
5424                 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]);
5425                 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]);
5426
5427                 // then the normals from the corners relative to origin
5428                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5429                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5430                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5431                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5432
5433                 // in a NORMAL view, forward cross left == up
5434                 // in a REFLECTED view, forward cross left == down
5435                 // so our cross products above need to be adjusted for a left handed coordinate system
5436                 CrossProduct(forward, left, v);
5437                 if(DotProduct(v, up) < 0)
5438                 {
5439                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5440                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5441                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5442                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5443                 }
5444
5445                 // Leaving those out was a mistake, those were in the old code, and they
5446                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5447                 // I couldn't reproduce it after adding those normalizations. --blub
5448                 VectorNormalize(r_refdef.view.frustum[0].normal);
5449                 VectorNormalize(r_refdef.view.frustum[1].normal);
5450                 VectorNormalize(r_refdef.view.frustum[2].normal);
5451                 VectorNormalize(r_refdef.view.frustum[3].normal);
5452
5453                 // make the corners absolute
5454                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5455                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5456                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5457                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5458
5459                 // one more normal
5460                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5461
5462                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5463                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5464                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5465                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5466                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5467         }
5468         else
5469         {
5470                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5471                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5472                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5473                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5474                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5475                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5476                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5477                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5478                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5479                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5480         }
5481         r_refdef.view.numfrustumplanes = 5;
5482
5483         if (r_refdef.view.useclipplane)
5484         {
5485                 r_refdef.view.numfrustumplanes = 6;
5486                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5487         }
5488
5489         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5490                 PlaneClassify(r_refdef.view.frustum + i);
5491
5492         // LordHavoc: note to all quake engine coders, Quake had a special case
5493         // for 90 degrees which assumed a square view (wrong), so I removed it,
5494         // Quake2 has it disabled as well.
5495
5496         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5497         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5498         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5499         //PlaneClassify(&frustum[0]);
5500
5501         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5502         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5503         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5504         //PlaneClassify(&frustum[1]);
5505
5506         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5507         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5508         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5509         //PlaneClassify(&frustum[2]);
5510
5511         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5512         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5513         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5514         //PlaneClassify(&frustum[3]);
5515
5516         // nearclip plane
5517         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5518         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5519         //PlaneClassify(&frustum[4]);
5520 }
5521
5522 static void R_View_UpdateWithScissor(const int *myscissor)
5523 {
5524         R_Main_ResizeViewCache();
5525         R_View_SetFrustum(myscissor);
5526         R_View_WorldVisibility(r_refdef.view.useclipplane);
5527         R_View_UpdateEntityVisible();
5528 }
5529
5530 static void R_View_Update(void)
5531 {
5532         R_Main_ResizeViewCache();
5533         R_View_SetFrustum(NULL);
5534         R_View_WorldVisibility(r_refdef.view.useclipplane);
5535         R_View_UpdateEntityVisible();
5536 }
5537
5538 float viewscalefpsadjusted = 1.0f;
5539
5540 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5541 {
5542         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5543         scale = bound(0.03125f, scale, 1.0f);
5544         *outwidth = (int)ceil(width * scale);
5545         *outheight = (int)ceil(height * scale);
5546 }
5547
5548 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5549 {
5550         const float *customclipplane = NULL;
5551         float plane[4];
5552         int /*rtwidth,*/ rtheight;
5553         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5554         {
5555                 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5556                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5557                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5558                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5559                         dist = r_refdef.view.clipplane.dist;
5560                 plane[0] = r_refdef.view.clipplane.normal[0];
5561                 plane[1] = r_refdef.view.clipplane.normal[1];
5562                 plane[2] = r_refdef.view.clipplane.normal[2];
5563                 plane[3] = -dist;
5564                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5565         }
5566
5567         //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5568         rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5569
5570         if (!r_refdef.view.useperspective)
5571                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -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);
5572         else if (vid.stencil && r_useinfinitefarclip.integer)
5573                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5574         else
5575                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5576         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5577         R_SetViewport(&r_refdef.view.viewport);
5578         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5579         {
5580                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5581                 float screenplane[4];
5582                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5583                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5584                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5585                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5586                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5587         }
5588 }
5589
5590 void R_EntityMatrix(const matrix4x4_t *matrix)
5591 {
5592         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5593         {
5594                 gl_modelmatrixchanged = false;
5595                 gl_modelmatrix = *matrix;
5596                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5597                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5598                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5599                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5600                 CHECKGLERROR
5601                 switch(vid.renderpath)
5602                 {
5603                 case RENDERPATH_D3D9:
5604 #ifdef SUPPORTD3D
5605                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5606                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5607 #endif
5608                         break;
5609                 case RENDERPATH_D3D10:
5610                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5611                         break;
5612                 case RENDERPATH_D3D11:
5613                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5614                         break;
5615                 case RENDERPATH_GL11:
5616                 case RENDERPATH_GL13:
5617                 case RENDERPATH_GLES1:
5618 #ifndef USE_GLES2
5619                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5620 #endif
5621                         break;
5622                 case RENDERPATH_SOFT:
5623                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5624                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5625                         break;
5626                 case RENDERPATH_GL20:
5627                 case RENDERPATH_GLES2:
5628                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5629                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5630                         break;
5631                 }
5632         }
5633 }
5634
5635 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5636 {
5637         r_viewport_t viewport;
5638
5639         CHECKGLERROR
5640
5641         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5642         R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5643         R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5644         R_SetViewport(&viewport);
5645         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5646         GL_Color(1, 1, 1, 1);
5647         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5648         GL_BlendFunc(GL_ONE, GL_ZERO);
5649         GL_ScissorTest(false);
5650         GL_DepthMask(false);
5651         GL_DepthRange(0, 1);
5652         GL_DepthTest(false);
5653         GL_DepthFunc(GL_LEQUAL);
5654         R_EntityMatrix(&identitymatrix);
5655         R_Mesh_ResetTextureState();
5656         GL_PolygonOffset(0, 0);
5657         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5658         switch(vid.renderpath)
5659         {
5660         case RENDERPATH_GL11:
5661         case RENDERPATH_GL13:
5662         case RENDERPATH_GL20:
5663         case RENDERPATH_GLES1:
5664         case RENDERPATH_GLES2:
5665                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5666                 break;
5667         case RENDERPATH_D3D9:
5668         case RENDERPATH_D3D10:
5669         case RENDERPATH_D3D11:
5670         case RENDERPATH_SOFT:
5671                 break;
5672         }
5673         GL_CullFace(GL_NONE);
5674
5675         CHECKGLERROR
5676 }
5677
5678 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5679 {
5680         DrawQ_Finish();
5681
5682         R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5683 }
5684
5685 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5686 {
5687         DrawQ_Finish();
5688
5689         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5690         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5691         GL_Color(1, 1, 1, 1);
5692         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5693         GL_BlendFunc(GL_ONE, GL_ZERO);
5694         GL_ScissorTest(true);
5695         GL_DepthMask(true);
5696         GL_DepthRange(0, 1);
5697         GL_DepthTest(true);
5698         GL_DepthFunc(GL_LEQUAL);
5699         R_EntityMatrix(&identitymatrix);
5700         R_Mesh_ResetTextureState();
5701         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5702         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5703         switch(vid.renderpath)
5704         {
5705         case RENDERPATH_GL11:
5706         case RENDERPATH_GL13:
5707         case RENDERPATH_GL20:
5708         case RENDERPATH_GLES1:
5709         case RENDERPATH_GLES2:
5710                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5711                 break;
5712         case RENDERPATH_D3D9:
5713         case RENDERPATH_D3D10:
5714         case RENDERPATH_D3D11:
5715         case RENDERPATH_SOFT:
5716                 break;
5717         }
5718         GL_CullFace(r_refdef.view.cullface_back);
5719 }
5720
5721 /*
5722 ================
5723 R_RenderView_UpdateViewVectors
5724 ================
5725 */
5726 void R_RenderView_UpdateViewVectors(void)
5727 {
5728         // break apart the view matrix into vectors for various purposes
5729         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5730         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5731         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5732         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5733         // make an inverted copy of the view matrix for tracking sprites
5734         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5735 }
5736
5737 static void R_Water_StartFrame(void)
5738 {
5739         int i;
5740         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5741         r_waterstate_waterplane_t *p;
5742         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;
5743
5744         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5745                 return;
5746
5747         switch(vid.renderpath)
5748         {
5749         case RENDERPATH_GL20:
5750         case RENDERPATH_D3D9:
5751         case RENDERPATH_D3D10:
5752         case RENDERPATH_D3D11:
5753         case RENDERPATH_SOFT:
5754         case RENDERPATH_GLES2:
5755                 break;
5756         case RENDERPATH_GL11:
5757         case RENDERPATH_GL13:
5758         case RENDERPATH_GLES1:
5759                 return;
5760         }
5761
5762         // set waterwidth and waterheight to the water resolution that will be
5763         // used (often less than the screen resolution for faster rendering)
5764         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5765
5766         // calculate desired texture sizes
5767         // can't use water if the card does not support the texture size
5768         if (!r_water.integer || r_showsurfaces.integer)
5769                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5770         else if (vid.support.arb_texture_non_power_of_two)
5771         {
5772                 texturewidth = waterwidth;
5773                 textureheight = waterheight;
5774                 camerawidth = waterwidth;
5775                 cameraheight = waterheight;
5776         }
5777         else
5778         {
5779                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5780                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5781                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5782                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5783         }
5784
5785         // allocate textures as needed
5786         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))
5787         {
5788                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5789                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5790                 {
5791                         if (p->texture_refraction)
5792                                 R_FreeTexture(p->texture_refraction);
5793                         p->texture_refraction = NULL;
5794                         if (p->fbo_refraction)
5795                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5796                         p->fbo_refraction = 0;
5797                         if (p->texture_reflection)
5798                                 R_FreeTexture(p->texture_reflection);
5799                         p->texture_reflection = NULL;
5800                         if (p->fbo_reflection)
5801                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5802                         p->fbo_reflection = 0;
5803                         if (p->texture_camera)
5804                                 R_FreeTexture(p->texture_camera);
5805                         p->texture_camera = NULL;
5806                         if (p->fbo_camera)
5807                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5808                         p->fbo_camera = 0;
5809                 }
5810                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5811                 r_fb.water.texturewidth = texturewidth;
5812                 r_fb.water.textureheight = textureheight;
5813                 r_fb.water.camerawidth = camerawidth;
5814                 r_fb.water.cameraheight = cameraheight;
5815         }
5816
5817         if (r_fb.water.texturewidth)
5818         {
5819                 int scaledwidth, scaledheight;
5820
5821                 r_fb.water.enabled = true;
5822
5823                 // water resolution is usually reduced
5824                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5825                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5826                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5827
5828                 // set up variables that will be used in shader setup
5829                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5830                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5831                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5832                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5833         }
5834
5835         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5836         r_fb.water.numwaterplanes = 0;
5837 }
5838
5839 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5840 {
5841         int planeindex, bestplaneindex, vertexindex;
5842         vec3_t mins, maxs, normal, center, v, n;
5843         vec_t planescore, bestplanescore;
5844         mplane_t plane;
5845         r_waterstate_waterplane_t *p;
5846         texture_t *t = R_GetCurrentTexture(surface->texture);
5847
5848         rsurface.texture = t;
5849         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5850         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5851         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5852                 return;
5853         // average the vertex normals, find the surface bounds (after deformvertexes)
5854         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5855         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5856         VectorCopy(n, normal);
5857         VectorCopy(v, mins);
5858         VectorCopy(v, maxs);
5859         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5860         {
5861                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5862                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5863                 VectorAdd(normal, n, normal);
5864                 mins[0] = min(mins[0], v[0]);
5865                 mins[1] = min(mins[1], v[1]);
5866                 mins[2] = min(mins[2], v[2]);
5867                 maxs[0] = max(maxs[0], v[0]);
5868                 maxs[1] = max(maxs[1], v[1]);
5869                 maxs[2] = max(maxs[2], v[2]);
5870         }
5871         VectorNormalize(normal);
5872         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5873
5874         VectorCopy(normal, plane.normal);
5875         VectorNormalize(plane.normal);
5876         plane.dist = DotProduct(center, plane.normal);
5877         PlaneClassify(&plane);
5878         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5879         {
5880                 // skip backfaces (except if nocullface is set)
5881 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5882 //                      return;
5883                 VectorNegate(plane.normal, plane.normal);
5884                 plane.dist *= -1;
5885                 PlaneClassify(&plane);
5886         }
5887
5888
5889         // find a matching plane if there is one
5890         bestplaneindex = -1;
5891         bestplanescore = 1048576.0f;
5892         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5893         {
5894                 if(p->camera_entity == t->camera_entity)
5895                 {
5896                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5897                         if (bestplaneindex < 0 || bestplanescore > planescore)
5898                         {
5899                                 bestplaneindex = planeindex;
5900                                 bestplanescore = planescore;
5901                         }
5902                 }
5903         }
5904         planeindex = bestplaneindex;
5905
5906         // if this surface does not fit any known plane rendered this frame, add one
5907         if (planeindex < 0 || bestplanescore > 0.001f)
5908         {
5909                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5910                 {
5911                         // store the new plane
5912                         planeindex = r_fb.water.numwaterplanes++;
5913                         p = r_fb.water.waterplanes + planeindex;
5914                         p->plane = plane;
5915                         // clear materialflags and pvs
5916                         p->materialflags = 0;
5917                         p->pvsvalid = false;
5918                         p->camera_entity = t->camera_entity;
5919                         VectorCopy(mins, p->mins);
5920                         VectorCopy(maxs, p->maxs);
5921                 }
5922                 else
5923                 {
5924                         // We're totally screwed.
5925                         return;
5926                 }
5927         }
5928         else
5929         {
5930                 // merge mins/maxs when we're adding this surface to the plane
5931                 p = r_fb.water.waterplanes + planeindex;
5932                 p->mins[0] = min(p->mins[0], mins[0]);
5933                 p->mins[1] = min(p->mins[1], mins[1]);
5934                 p->mins[2] = min(p->mins[2], mins[2]);
5935                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5936                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5937                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5938         }
5939         // merge this surface's materialflags into the waterplane
5940         p->materialflags |= t->currentmaterialflags;
5941         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5942         {
5943                 // merge this surface's PVS into the waterplane
5944                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5945                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5946                 {
5947                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5948                         p->pvsvalid = true;
5949                 }
5950         }
5951 }
5952
5953 extern cvar_t r_drawparticles;
5954 extern cvar_t r_drawdecals;
5955
5956 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
5957 {
5958         int myscissor[4];
5959         r_refdef_view_t originalview;
5960         r_refdef_view_t myview;
5961         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;
5962         int waterx, watery;
5963         r_waterstate_waterplane_t *p;
5964         vec3_t visorigin;
5965         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;
5966         char vabuf[1024];
5967
5968         originalview = r_refdef.view;
5969         waterx = usewaterfbo ? 0 : x;
5970         watery = usewaterfbo ? 0 : y;
5971
5972         // lowquality hack, temporarily shut down some cvars and restore afterwards
5973         qualityreduction = r_water_lowquality.integer;
5974         if (qualityreduction > 0)
5975         {
5976                 if (qualityreduction >= 1)
5977                 {
5978                         old_r_shadows = r_shadows.integer;
5979                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5980                         old_r_dlight = r_shadow_realtime_dlight.integer;
5981                         Cvar_SetValueQuick(&r_shadows, 0);
5982                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5984                 }
5985                 if (qualityreduction >= 2)
5986                 {
5987                         old_r_dynamic = r_dynamic.integer;
5988                         old_r_particles = r_drawparticles.integer;
5989                         old_r_decals = r_drawdecals.integer;
5990                         Cvar_SetValueQuick(&r_dynamic, 0);
5991                         Cvar_SetValueQuick(&r_drawparticles, 0);
5992                         Cvar_SetValueQuick(&r_drawdecals, 0);
5993                 }
5994         }
5995
5996         // make sure enough textures are allocated
5997         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5998         {
5999                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6000                         continue;
6001                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6002                 {
6003                         if (!p->texture_refraction)
6004                                 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);
6005                         if (!p->texture_refraction)
6006                                 goto error;
6007                         if (usewaterfbo)
6008                         {
6009                                 if (r_fb.water.depthtexture == NULL)
6010                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6011                                 if (p->fbo_refraction == 0)
6012                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6013                         }
6014                 }
6015                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6016                 {
6017                         if (!p->texture_camera)
6018                                 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);
6019                         if (!p->texture_camera)
6020                                 goto error;
6021                         if (usewaterfbo)
6022                         {
6023                                 if (r_fb.water.depthtexture == NULL)
6024                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6025                                 if (p->fbo_camera == 0)
6026                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6027                         }
6028                 }
6029
6030                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6031                 {
6032                         if (!p->texture_reflection)
6033                                 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);
6034                         if (!p->texture_reflection)
6035                                 goto error;
6036                         if (usewaterfbo)
6037                         {
6038                                 if (r_fb.water.depthtexture == NULL)
6039                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6040                                 if (p->fbo_reflection == 0)
6041                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6042                         }
6043                 }
6044         }
6045
6046         // render views
6047         r_refdef.view = originalview;
6048         r_refdef.view.showdebug = false;
6049         r_refdef.view.x = waterx;
6050         r_refdef.view.y = watery;
6051         r_refdef.view.width = r_fb.water.waterwidth;
6052         r_refdef.view.height = r_fb.water.waterheight;
6053         r_refdef.view.useclipplane = true;
6054         myview = r_refdef.view;
6055         r_fb.water.renderingscene = true;
6056         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6057         {
6058                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6059                         continue;
6060                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6061                 {
6062                         r_refdef.view = myview;
6063                         if(r_water_scissormode.integer)
6064                         {
6065                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6066                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6067                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6068                         }
6069
6070                         // render reflected scene and copy into texture
6071                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6072                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6073                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6074                         r_refdef.view.clipplane = p->plane;
6075                         // reverse the cullface settings for this render
6076                         r_refdef.view.cullface_front = GL_FRONT;
6077                         r_refdef.view.cullface_back = GL_BACK;
6078                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6079                         {
6080                                 r_refdef.view.usecustompvs = true;
6081                                 if (p->pvsvalid)
6082                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6083                                 else
6084                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6085                         }
6086
6087                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6088                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6089                         if (p->fbo_reflection)
6090                                 GL_ScissorTest(false);
6091                         R_ClearScreen(r_refdef.fogenabled);
6092                         if (p->fbo_reflection)
6093                                 GL_ScissorTest(true);
6094                         if(r_water_scissormode.integer & 2)
6095                                 R_View_UpdateWithScissor(myscissor);
6096                         else
6097                                 R_View_Update();
6098                         R_AnimCache_CacheVisibleEntities();
6099                         if(r_water_scissormode.integer & 1)
6100                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6101                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6102
6103                         if (!p->fbo_reflection)
6104                                 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6105                         r_fb.water.hideplayer = false;
6106                 }
6107
6108                 // render the normal view scene and copy into texture
6109                 // (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)
6110                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6111                 {
6112                         r_refdef.view = myview;
6113                         if(r_water_scissormode.integer)
6114                         {
6115                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6116                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6117                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6118                         }
6119
6120                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6121
6122                         r_refdef.view.clipplane = p->plane;
6123                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6124                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6125
6126                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6127                         {
6128                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6129                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6130                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6131                                 R_RenderView_UpdateViewVectors();
6132                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6133                                 {
6134                                         r_refdef.view.usecustompvs = true;
6135                                         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);
6136                                 }
6137                         }
6138
6139                         PlaneClassify(&r_refdef.view.clipplane);
6140
6141                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6142                         if (p->fbo_refraction)
6143                                 GL_ScissorTest(false);
6144                         R_ClearScreen(r_refdef.fogenabled);
6145                         if (p->fbo_refraction)
6146                                 GL_ScissorTest(true);
6147                         if(r_water_scissormode.integer & 2)
6148                                 R_View_UpdateWithScissor(myscissor);
6149                         else
6150                                 R_View_Update();
6151                         R_AnimCache_CacheVisibleEntities();
6152                         if(r_water_scissormode.integer & 1)
6153                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6154                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6155
6156                         if (!p->fbo_refraction)
6157                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, waterx, watery, r_fb.water.waterwidth, r_fb.water.waterheight);
6158                         r_fb.water.hideplayer = false;
6159                 }
6160                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6161                 {
6162                         r_refdef.view = myview;
6163
6164                         r_refdef.view.clipplane = p->plane;
6165                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6166                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6167
6168                         r_refdef.view.x = waterx;
6169                         r_refdef.view.y = watery;
6170                         r_refdef.view.width = r_fb.water.camerawidth;
6171                         r_refdef.view.height = r_fb.water.cameraheight;
6172                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6173                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6174                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6175                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6176
6177                         if(p->camera_entity)
6178                         {
6179                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6180                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6181                         }
6182
6183                         // note: all of the view is used for displaying... so
6184                         // there is no use in scissoring
6185
6186                         // reverse the cullface settings for this render
6187                         r_refdef.view.cullface_front = GL_FRONT;
6188                         r_refdef.view.cullface_back = GL_BACK;
6189                         // also reverse the view matrix
6190                         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
6191                         R_RenderView_UpdateViewVectors();
6192                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6193                         {
6194                                 r_refdef.view.usecustompvs = true;
6195                                 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);
6196                         }
6197                         
6198                         // camera needs no clipplane
6199                         r_refdef.view.useclipplane = false;
6200
6201                         PlaneClassify(&r_refdef.view.clipplane);
6202
6203                         r_fb.water.hideplayer = false;
6204
6205                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
6206                         if (p->fbo_camera)
6207                                 GL_ScissorTest(false);
6208                         R_ClearScreen(r_refdef.fogenabled);
6209                         if (p->fbo_camera)
6210                                 GL_ScissorTest(true);
6211                         R_View_Update();
6212                         R_AnimCache_CacheVisibleEntities();
6213                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
6214
6215                         if (!p->fbo_camera)
6216                                 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, waterx, watery, r_fb.water.camerawidth, r_fb.water.cameraheight);
6217                         r_fb.water.hideplayer = false;
6218                 }
6219
6220         }
6221         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6222         r_fb.water.renderingscene = false;
6223         r_refdef.view = originalview;
6224         R_ResetViewRendering3D(fbo, depthtexture, colortexture, x, y, width, height);
6225         if (!r_fb.water.depthtexture)
6226                 R_ClearScreen(r_refdef.fogenabled);
6227         R_View_Update();
6228         R_AnimCache_CacheVisibleEntities();
6229         goto finish;
6230 error:
6231         r_refdef.view = originalview;
6232         r_fb.water.renderingscene = false;
6233         Cvar_SetValueQuick(&r_water, 0);
6234         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6235 finish:
6236         // lowquality hack, restore cvars
6237         if (qualityreduction > 0)
6238         {
6239                 if (qualityreduction >= 1)
6240                 {
6241                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6242                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6243                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6244                 }
6245                 if (qualityreduction >= 2)
6246                 {
6247                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6248                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6249                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6250                 }
6251         }
6252 }
6253
6254 static void R_Bloom_StartFrame(void)
6255 {
6256         int i;
6257         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6258         int viewwidth, viewheight;
6259         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6260         textype_t textype = TEXTYPE_COLORBUFFER;
6261
6262         switch (vid.renderpath)
6263         {
6264         case RENDERPATH_GL20:
6265                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6266                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6267                 {
6268                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6269                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6270                 }
6271                 break;
6272         case RENDERPATH_GL11:
6273         case RENDERPATH_GL13:
6274         case RENDERPATH_GLES1:
6275                 return; // don't bother
6276         case RENDERPATH_GLES2:
6277         case RENDERPATH_D3D9:
6278         case RENDERPATH_D3D10:
6279         case RENDERPATH_D3D11:
6280                 r_fb.usedepthtextures = false;
6281                 break;
6282         case RENDERPATH_SOFT:
6283                 r_fb.usedepthtextures = true;
6284                 break;
6285         }
6286
6287         if (r_viewscale_fpsscaling.integer)
6288         {
6289                 double actualframetime;
6290                 double targetframetime;
6291                 double adjust;
6292                 actualframetime = r_refdef.lastdrawscreentime;
6293                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6294                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6295                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6296                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6297                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6298                 viewscalefpsadjusted += adjust;
6299                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6300         }
6301         else
6302                 viewscalefpsadjusted = 1.0f;
6303
6304         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6305
6306         switch(vid.renderpath)
6307         {
6308         case RENDERPATH_GL20:
6309         case RENDERPATH_D3D9:
6310         case RENDERPATH_D3D10:
6311         case RENDERPATH_D3D11:
6312         case RENDERPATH_SOFT:
6313         case RENDERPATH_GLES2:
6314                 break;
6315         case RENDERPATH_GL11:
6316         case RENDERPATH_GL13:
6317         case RENDERPATH_GLES1:
6318                 return;
6319         }
6320
6321         // set bloomwidth and bloomheight to the bloom resolution that will be
6322         // used (often less than the screen resolution for faster rendering)
6323         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6324         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6325         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6326         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6327         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6328
6329         // calculate desired texture sizes
6330         if (vid.support.arb_texture_non_power_of_two)
6331         {
6332                 screentexturewidth = vid.width;
6333                 screentextureheight = vid.height;
6334                 bloomtexturewidth = r_fb.bloomwidth;
6335                 bloomtextureheight = r_fb.bloomheight;
6336         }
6337         else
6338         {
6339                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6340                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6341                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6342                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6343         }
6344
6345         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))
6346         {
6347                 Cvar_SetValueQuick(&r_bloom, 0);
6348                 Cvar_SetValueQuick(&r_motionblur, 0);
6349                 Cvar_SetValueQuick(&r_damageblur, 0);
6350         }
6351
6352         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6353          && !r_bloom.integer
6354          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6355          && !useviewfbo
6356          && r_viewscale.value == 1.0f
6357          && !r_viewscale_fpsscaling.integer)
6358                 screentexturewidth = screentextureheight = 0;
6359         if (!r_bloom.integer)
6360                 bloomtexturewidth = bloomtextureheight = 0;
6361
6362         // allocate textures as needed
6363         if (r_fb.screentexturewidth != screentexturewidth
6364          || r_fb.screentextureheight != screentextureheight
6365          || r_fb.bloomtexturewidth != bloomtexturewidth
6366          || r_fb.bloomtextureheight != bloomtextureheight
6367          || r_fb.textype != textype
6368          || useviewfbo != (r_fb.fbo != 0))
6369         {
6370                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6371                 {
6372                         if (r_fb.bloomtexture[i])
6373                                 R_FreeTexture(r_fb.bloomtexture[i]);
6374                         r_fb.bloomtexture[i] = NULL;
6375
6376                         if (r_fb.bloomfbo[i])
6377                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6378                         r_fb.bloomfbo[i] = 0;
6379                 }
6380
6381                 if (r_fb.fbo)
6382                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6383                 r_fb.fbo = 0;
6384
6385                 if (r_fb.colortexture)
6386                         R_FreeTexture(r_fb.colortexture);
6387                 r_fb.colortexture = NULL;
6388
6389                 if (r_fb.depthtexture)
6390                         R_FreeTexture(r_fb.depthtexture);
6391                 r_fb.depthtexture = NULL;
6392
6393                 if (r_fb.ghosttexture)
6394                         R_FreeTexture(r_fb.ghosttexture);
6395                 r_fb.ghosttexture = NULL;
6396
6397                 r_fb.screentexturewidth = screentexturewidth;
6398                 r_fb.screentextureheight = screentextureheight;
6399                 r_fb.bloomtexturewidth = bloomtexturewidth;
6400                 r_fb.bloomtextureheight = bloomtextureheight;
6401                 r_fb.textype = textype;
6402
6403                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6404                 {
6405                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6406                                 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);
6407                         r_fb.ghosttexture_valid = false;
6408                         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);
6409                         if (useviewfbo)
6410                         {
6411                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6412                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6413                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6414                         }
6415                 }
6416
6417                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6418                 {
6419                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6420                         {
6421                                 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);
6422                                 if (useviewfbo)
6423                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6424                         }
6425                 }
6426         }
6427
6428         // bloom texture is a different resolution
6429         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6430         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6431         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6432         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6433         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6434
6435         // set up a texcoord array for the full resolution screen image
6436         // (we have to keep this around to copy back during final render)
6437         r_fb.screentexcoord2f[0] = 0;
6438         r_fb.screentexcoord2f[1] = 1.0f;
6439         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6440         r_fb.screentexcoord2f[3] = 1.0f;
6441         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6442         r_fb.screentexcoord2f[5] = 1.0f - (float)viewheight / (float)r_fb.screentextureheight;
6443         r_fb.screentexcoord2f[6] = 0;
6444         r_fb.screentexcoord2f[7] = 1.0f - (float)viewheight / (float)r_fb.screentextureheight;
6445
6446         // set up a texcoord array for the reduced resolution bloom image
6447         // (which will be additive blended over the screen image)
6448         r_fb.bloomtexcoord2f[0] = 0;
6449         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6450         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6451         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6452         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6453         r_fb.bloomtexcoord2f[5] = 0;
6454         r_fb.bloomtexcoord2f[6] = 0;
6455         r_fb.bloomtexcoord2f[7] = 0;
6456
6457         switch(vid.renderpath)
6458         {
6459         case RENDERPATH_GL11:
6460         case RENDERPATH_GL13:
6461         case RENDERPATH_GL20:
6462         case RENDERPATH_SOFT:
6463         case RENDERPATH_GLES1:
6464         case RENDERPATH_GLES2:
6465                 break;
6466         case RENDERPATH_D3D9:
6467         case RENDERPATH_D3D10:
6468         case RENDERPATH_D3D11:
6469                 for (i = 0;i < 4;i++)
6470                 {
6471                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6472                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6473                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6474                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6475                 }
6476                 break;
6477         }
6478
6479         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_fb.fbo ? 0 : r_refdef.view.x, r_fb.fbo ? 0 : r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6480
6481         if (r_fb.fbo)
6482                 r_refdef.view.clear = true;
6483 }
6484
6485 static void R_Bloom_MakeTexture(void)
6486 {
6487         int x, range, dir;
6488         float xoffset, yoffset, r, brighten;
6489         rtexture_t *intex;
6490         float colorscale = r_bloom_colorscale.value;
6491
6492         r_refdef.stats[r_stat_bloom]++;
6493     
6494 #if 0
6495     // this copy is unnecessary since it happens in R_BlendView already
6496         if (!r_fb.fbo)
6497         {
6498                 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);
6499                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6500         }
6501 #endif
6502
6503         // scale down screen texture to the bloom texture size
6504         CHECKGLERROR
6505         r_fb.bloomindex = 0;
6506         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6507         R_SetViewport(&r_fb.bloomviewport);
6508         GL_CullFace(GL_NONE);
6509         GL_DepthTest(false);
6510         GL_BlendFunc(GL_ONE, GL_ZERO);
6511         GL_Color(colorscale, colorscale, colorscale, 1);
6512         // 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...
6513         switch(vid.renderpath)
6514         {
6515         case RENDERPATH_GL11:
6516         case RENDERPATH_GL13:
6517         case RENDERPATH_GL20:
6518         case RENDERPATH_GLES1:
6519         case RENDERPATH_GLES2:
6520         case RENDERPATH_SOFT:
6521                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6522                 break;
6523         case RENDERPATH_D3D9:
6524         case RENDERPATH_D3D10:
6525         case RENDERPATH_D3D11:
6526                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6527                 break;
6528         }
6529         // TODO: do boxfilter scale-down in shader?
6530         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6531         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6532         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6533
6534         // we now have a properly scaled bloom image
6535         if (!r_fb.bloomfbo[r_fb.bloomindex])
6536         {
6537                 // copy it into the bloom texture
6538                 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);
6539                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6540         }
6541
6542         // multiply bloom image by itself as many times as desired
6543         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6544         {
6545                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6546                 r_fb.bloomindex ^= 1;
6547                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6548                 x *= 2;
6549                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6550                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6551                 {
6552                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6553                         GL_Color(r,r,r,1); // apply fix factor
6554                 }
6555                 else
6556                 {
6557                         if(x <= 2)
6558                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6559                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6560                         GL_Color(1,1,1,1); // no fix factor supported here
6561                 }
6562                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6563                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6564                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6565                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6566
6567                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6568                 {
6569                         // copy the darkened image to a texture
6570                         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);
6571                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6572                 }
6573         }
6574
6575         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6576         brighten = r_bloom_brighten.value;
6577         brighten = sqrt(brighten);
6578         if(range >= 1)
6579                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6580
6581         for (dir = 0;dir < 2;dir++)
6582         {
6583                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6584                 r_fb.bloomindex ^= 1;
6585                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6586                 // blend on at multiple vertical offsets to achieve a vertical blur
6587                 // TODO: do offset blends using GLSL
6588                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6589                 GL_BlendFunc(GL_ONE, GL_ZERO);
6590                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6591                 for (x = -range;x <= range;x++)
6592                 {
6593                         if (!dir){xoffset = 0;yoffset = x;}
6594                         else {xoffset = x;yoffset = 0;}
6595                         xoffset /= (float)r_fb.bloomtexturewidth;
6596                         yoffset /= (float)r_fb.bloomtextureheight;
6597                         // compute a texcoord array with the specified x and y offset
6598                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6599                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6600                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6601                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6602                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6603                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6604                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6605                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6606                         // this r value looks like a 'dot' particle, fading sharply to
6607                         // black at the edges
6608                         // (probably not realistic but looks good enough)
6609                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6610                         //r = brighten/(range*2+1);
6611                         r = brighten / (range * 2 + 1);
6612                         if(range >= 1)
6613                                 r *= (1 - x*x/(float)(range*range));
6614                         GL_Color(r, r, r, 1);
6615                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6616                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6617                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6618                         GL_BlendFunc(GL_ONE, GL_ONE);
6619                 }
6620
6621                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6622                 {
6623                         // copy the vertically or horizontally blurred bloom view to a texture
6624                         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);
6625                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6626                 }
6627         }
6628 }
6629
6630 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6631 {
6632         dpuint64 permutation;
6633         float uservecs[4][4];
6634
6635         R_EntityMatrix(&identitymatrix);
6636
6637         switch (vid.renderpath)
6638         {
6639         case RENDERPATH_GL20:
6640         case RENDERPATH_D3D9:
6641         case RENDERPATH_D3D10:
6642         case RENDERPATH_D3D11:
6643         case RENDERPATH_SOFT:
6644         case RENDERPATH_GLES2:
6645                 permutation =
6646                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6647                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6648                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6649                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6650                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6651
6652                 if (r_fb.colortexture)
6653                 {
6654                         if (!r_fb.fbo)
6655                         {
6656                                 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);
6657                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6658                         }
6659
6660                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6661                         {
6662                                 // declare variables
6663                                 float blur_factor, blur_mouseaccel, blur_velocity;
6664                                 static float blur_average; 
6665                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6666
6667                                 // set a goal for the factoring
6668                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6669                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6670                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6671                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6672                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6673                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6674
6675                                 // from the goal, pick an averaged value between goal and last value
6676                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6677                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6678
6679                                 // enforce minimum amount of blur 
6680                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6681
6682                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6683
6684                                 // calculate values into a standard alpha
6685                                 cl.motionbluralpha = 1 - exp(-
6686                                                 (
6687                                                  (r_motionblur.value * blur_factor / 80)
6688                                                  +
6689                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6690                                                 )
6691                                                 /
6692                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6693                                           );
6694
6695                                 // randomization for the blur value to combat persistent ghosting
6696                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6697                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6698
6699                                 // apply the blur
6700                                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6701                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6702                                 {
6703                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6704                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6705                                         switch(vid.renderpath)
6706                                         {
6707                                         case RENDERPATH_GL11:
6708                                         case RENDERPATH_GL13:
6709                                         case RENDERPATH_GL20:
6710                                         case RENDERPATH_GLES1:
6711                                         case RENDERPATH_GLES2:
6712                                         case RENDERPATH_SOFT:
6713                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6714                                                 break;
6715                                         case RENDERPATH_D3D9:
6716                                         case RENDERPATH_D3D10:
6717                                         case RENDERPATH_D3D11:
6718                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6719                                                 break;
6720                                         }
6721                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6722                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6723                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6724                                 }
6725
6726                                 // updates old view angles for next pass
6727                                 VectorCopy(cl.viewangles, blur_oldangles);
6728
6729                                 // copy view into the ghost texture
6730                                 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);
6731                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6732                                 r_fb.ghosttexture_valid = true;
6733                         }
6734                 }
6735                 else
6736                 {
6737                         // no r_fb.colortexture means we're rendering to the real fb
6738                         // we may still have to do view tint...
6739                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6740                         {
6741                                 // apply a color tint to the whole view
6742                                 R_ResetViewRendering2D(0, NULL, NULL, viewx, viewy, viewwidth, viewheight);
6743                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6744                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6745                                 R_SetupShader_Generic_NoTexture(false, true);
6746                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6747                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6748                         }
6749                         break; // no screen processing, no bloom, skip it
6750                 }
6751
6752                 if (r_fb.bloomtexture[0])
6753                 {
6754                         // make the bloom texture
6755                         R_Bloom_MakeTexture();
6756                 }
6757
6758 #if _MSC_VER >= 1400
6759 #define sscanf sscanf_s
6760 #endif
6761                 memset(uservecs, 0, sizeof(uservecs));
6762                 if (r_glsl_postprocess_uservec1_enable.integer)
6763                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6764                 if (r_glsl_postprocess_uservec2_enable.integer)
6765                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6766                 if (r_glsl_postprocess_uservec3_enable.integer)
6767                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6768                 if (r_glsl_postprocess_uservec4_enable.integer)
6769                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6770
6771                 // render to the screen fbo
6772                 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6773                 GL_Color(1, 1, 1, 1);
6774                 GL_BlendFunc(GL_ONE, GL_ZERO);
6775
6776                 switch(vid.renderpath)
6777                 {
6778                 case RENDERPATH_GL20:
6779                 case RENDERPATH_GLES2:
6780                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6781                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6782                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6783                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6784                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6785                         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]);
6786                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6787                         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]);
6788                         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]);
6789                         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]);
6790                         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]);
6791                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6792                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6793                         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);
6794                         break;
6795                 case RENDERPATH_D3D9:
6796 #ifdef SUPPORTD3D
6797                         // 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...
6798                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6799                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6800                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6801                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6802                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6803                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6804                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6805                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6806                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6807                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6808                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6809                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6810                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6811                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6812 #endif
6813                         break;
6814                 case RENDERPATH_D3D10:
6815                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6816                         break;
6817                 case RENDERPATH_D3D11:
6818                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6819                         break;
6820                 case RENDERPATH_SOFT:
6821                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6822                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6823                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6824                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6825                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6826                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6827                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6828                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6829                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6830                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6831                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6832                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6833                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6834                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6835                         break;
6836                 default:
6837                         break;
6838                 }
6839                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6840                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6841                 break;
6842         case RENDERPATH_GL11:
6843         case RENDERPATH_GL13:
6844         case RENDERPATH_GLES1:
6845                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6846                 {
6847                         // apply a color tint to the whole view
6848                         R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6849                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6850                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6851                         R_SetupShader_Generic_NoTexture(false, true);
6852                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6853                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854                 }
6855                 break;
6856         }
6857 }
6858
6859 matrix4x4_t r_waterscrollmatrix;
6860
6861 void R_UpdateFog(void)
6862 {
6863         // Nehahra fog
6864         if (gamemode == GAME_NEHAHRA)
6865         {
6866                 if (gl_fogenable.integer)
6867                 {
6868                         r_refdef.oldgl_fogenable = true;
6869                         r_refdef.fog_density = gl_fogdensity.value;
6870                         r_refdef.fog_red = gl_fogred.value;
6871                         r_refdef.fog_green = gl_foggreen.value;
6872                         r_refdef.fog_blue = gl_fogblue.value;
6873                         r_refdef.fog_alpha = 1;
6874                         r_refdef.fog_start = 0;
6875                         r_refdef.fog_end = gl_skyclip.value;
6876                         r_refdef.fog_height = 1<<30;
6877                         r_refdef.fog_fadedepth = 128;
6878                 }
6879                 else if (r_refdef.oldgl_fogenable)
6880                 {
6881                         r_refdef.oldgl_fogenable = false;
6882                         r_refdef.fog_density = 0;
6883                         r_refdef.fog_red = 0;
6884                         r_refdef.fog_green = 0;
6885                         r_refdef.fog_blue = 0;
6886                         r_refdef.fog_alpha = 0;
6887                         r_refdef.fog_start = 0;
6888                         r_refdef.fog_end = 0;
6889                         r_refdef.fog_height = 1<<30;
6890                         r_refdef.fog_fadedepth = 128;
6891                 }
6892         }
6893
6894         // fog parms
6895         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6896         r_refdef.fog_start = max(0, r_refdef.fog_start);
6897         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6898
6899         if (r_refdef.fog_density && r_drawfog.integer)
6900         {
6901                 r_refdef.fogenabled = true;
6902                 // this is the point where the fog reaches 0.9986 alpha, which we
6903                 // consider a good enough cutoff point for the texture
6904                 // (0.9986 * 256 == 255.6)
6905                 if (r_fog_exp2.integer)
6906                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6907                 else
6908                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6909                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6910                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6911                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6912                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6913                         R_BuildFogHeightTexture();
6914                 // fog color was already set
6915                 // update the fog texture
6916                 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)
6917                         R_BuildFogTexture();
6918                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6919                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6920         }
6921         else
6922                 r_refdef.fogenabled = false;
6923
6924         // fog color
6925         if (r_refdef.fog_density)
6926         {
6927                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6928                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6929                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6930
6931                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6932                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6933                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6934                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6935
6936                 {
6937                         vec3_t fogvec;
6938                         VectorCopy(r_refdef.fogcolor, fogvec);
6939                         //   color.rgb *= ContrastBoost * SceneBrightness;
6940                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6941                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6942                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6943                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6944                 }
6945         }
6946 }
6947
6948 void R_UpdateVariables(void)
6949 {
6950         R_Textures_Frame();
6951
6952         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6953
6954         r_refdef.farclip = r_farclip_base.value;
6955         if (r_refdef.scene.worldmodel)
6956                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6957         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6958
6959         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6960                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6961         r_refdef.polygonfactor = 0;
6962         r_refdef.polygonoffset = 0;
6963         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6964         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6965
6966         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6967         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6968         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6969         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6970         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6971         if (FAKELIGHT_ENABLED)
6972         {
6973                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6974         }
6975         else if (r_refdef.scene.worldmodel)
6976         {
6977                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6978         }
6979         if (r_showsurfaces.integer)
6980         {
6981                 r_refdef.scene.rtworld = false;
6982                 r_refdef.scene.rtworldshadows = false;
6983                 r_refdef.scene.rtdlight = false;
6984                 r_refdef.scene.rtdlightshadows = false;
6985                 r_refdef.scene.lightmapintensity = 0;
6986         }
6987
6988         r_gpuskeletal = false;
6989         switch(vid.renderpath)
6990         {
6991         case RENDERPATH_GL20:
6992                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6993         case RENDERPATH_D3D9:
6994         case RENDERPATH_D3D10:
6995         case RENDERPATH_D3D11:
6996         case RENDERPATH_SOFT:
6997         case RENDERPATH_GLES2:
6998                 if(!vid_gammatables_trivial)
6999                 {
7000                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7001                         {
7002                                 // build GLSL gamma texture
7003 #define RAMPWIDTH 256
7004                                 unsigned short ramp[RAMPWIDTH * 3];
7005                                 unsigned char rampbgr[RAMPWIDTH][4];
7006                                 int i;
7007
7008                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7009
7010                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7011                                 for(i = 0; i < RAMPWIDTH; ++i)
7012                                 {
7013                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7014                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7015                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7016                                         rampbgr[i][3] = 0;
7017                                 }
7018                                 if (r_texture_gammaramps)
7019                                 {
7020                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7021                                 }
7022                                 else
7023                                 {
7024                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7025                                 }
7026                         }
7027                 }
7028                 else
7029                 {
7030                         // remove GLSL gamma texture
7031                 }
7032                 break;
7033         case RENDERPATH_GL11:
7034         case RENDERPATH_GL13:
7035         case RENDERPATH_GLES1:
7036                 break;
7037         }
7038 }
7039
7040 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7041 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7042 /*
7043 ================
7044 R_SelectScene
7045 ================
7046 */
7047 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7048         if( scenetype != r_currentscenetype ) {
7049                 // store the old scenetype
7050                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7051                 r_currentscenetype = scenetype;
7052                 // move in the new scene
7053                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7054         }
7055 }
7056
7057 /*
7058 ================
7059 R_GetScenePointer
7060 ================
7061 */
7062 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7063 {
7064         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7065         if( scenetype == r_currentscenetype ) {
7066                 return &r_refdef.scene;
7067         } else {
7068                 return &r_scenes_store[ scenetype ];
7069         }
7070 }
7071
7072 static int R_SortEntities_Compare(const void *ap, const void *bp)
7073 {
7074         const entity_render_t *a = *(const entity_render_t **)ap;
7075         const entity_render_t *b = *(const entity_render_t **)bp;
7076
7077         // 1. compare model
7078         if(a->model < b->model)
7079                 return -1;
7080         if(a->model > b->model)
7081                 return +1;
7082
7083         // 2. compare skin
7084         // TODO possibly calculate the REAL skinnum here first using
7085         // skinscenes?
7086         if(a->skinnum < b->skinnum)
7087                 return -1;
7088         if(a->skinnum > b->skinnum)
7089                 return +1;
7090
7091         // everything we compared is equal
7092         return 0;
7093 }
7094 static void R_SortEntities(void)
7095 {
7096         // below or equal 2 ents, sorting never gains anything
7097         if(r_refdef.scene.numentities <= 2)
7098                 return;
7099         // sort
7100         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7101 }
7102
7103 /*
7104 ================
7105 R_RenderView
7106 ================
7107 */
7108 int dpsoftrast_test;
7109 extern cvar_t r_shadow_bouncegrid;
7110 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
7111 {
7112         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7113         int viewfbo = 0;
7114         rtexture_t *viewdepthtexture = NULL;
7115         rtexture_t *viewcolortexture = NULL;
7116         int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
7117
7118         dpsoftrast_test = r_test.integer;
7119
7120         if (r_timereport_active)
7121                 R_TimeReport("start");
7122         r_textureframe++; // used only by R_GetCurrentTexture
7123         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7124
7125         if(R_CompileShader_CheckStaticParms())
7126                 R_GLSL_Restart_f();
7127
7128         if (!r_drawentities.integer)
7129                 r_refdef.scene.numentities = 0;
7130         else if (r_sortentities.integer)
7131                 R_SortEntities();
7132
7133         R_AnimCache_ClearCache();
7134
7135         /* adjust for stereo display */
7136         if(R_Stereo_Active())
7137         {
7138                 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);
7139                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7140         }
7141
7142         if (r_refdef.view.isoverlay)
7143         {
7144                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7145                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7146                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7147                 R_TimeReport("depthclear");
7148
7149                 r_refdef.view.showdebug = false;
7150
7151                 r_fb.water.enabled = false;
7152                 r_fb.water.numwaterplanes = 0;
7153
7154                 R_RenderScene(fbo, depthtexture, colortexture, x, y, width, height);
7155
7156                 r_refdef.view.matrix = originalmatrix;
7157
7158                 CHECKGLERROR
7159                 return;
7160         }
7161
7162         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7163         {
7164                 r_refdef.view.matrix = originalmatrix;
7165                 return;
7166         }
7167
7168         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7169
7170         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7171                 // in sRGB fallback, behave similar to true sRGB: convert this
7172                 // value from linear to sRGB
7173                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7174
7175         R_RenderView_UpdateViewVectors();
7176
7177         R_Shadow_UpdateWorldLightSelection();
7178
7179         // this will set up r_fb.fbo
7180         R_Bloom_StartFrame();
7181
7182         // apply bloom brightness offset
7183         if(r_fb.bloomtexture[0])
7184                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7185
7186         // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
7187         if (r_fb.fbo)
7188         {
7189                 viewfbo = r_fb.fbo;
7190                 viewdepthtexture = r_fb.depthtexture;
7191                 viewcolortexture = r_fb.colortexture;
7192                 viewx = 0;
7193                 viewy = 0;
7194                 viewwidth = width;
7195                 viewheight = height;
7196         }
7197
7198         R_Water_StartFrame();
7199
7200         CHECKGLERROR
7201         if (r_timereport_active)
7202                 R_TimeReport("viewsetup");
7203
7204         R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7205
7206         // clear the whole fbo every frame - otherwise the driver will consider
7207         // it to be an inter-frame texture and stall in multi-gpu configurations
7208         if (viewfbo)
7209                 GL_ScissorTest(false);
7210         R_ClearScreen(r_refdef.fogenabled);
7211         if (r_timereport_active)
7212                 R_TimeReport("viewclear");
7213
7214         r_refdef.view.clear = true;
7215
7216         r_refdef.view.showdebug = true;
7217
7218         R_View_Update();
7219         if (r_timereport_active)
7220                 R_TimeReport("visibility");
7221
7222         R_AnimCache_CacheVisibleEntities();
7223         if (r_timereport_active)
7224                 R_TimeReport("animcache");
7225
7226         R_Shadow_UpdateBounceGridTexture();
7227         if (r_timereport_active && r_shadow_bouncegrid.integer)
7228                 R_TimeReport("bouncegrid");
7229
7230         r_fb.water.numwaterplanes = 0;
7231         if (r_fb.water.enabled)
7232                 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7233
7234         // for the actual view render we use scissoring a fair amount, so scissor
7235         // test needs to be on
7236         if (viewfbo)
7237                 GL_ScissorTest(true);
7238         GL_Scissor(viewx, viewy, viewwidth, viewheight);
7239         R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7240         r_fb.water.numwaterplanes = 0;
7241
7242         // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7243         GL_ScissorTest(false);
7244
7245         // R_BlendView will render the viewfbo image into the provided fbo using
7246         // the postprocess shader (including gamma correction and sRGB)
7247         R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7248         if (r_timereport_active)
7249                 R_TimeReport("blendview");
7250
7251         r_refdef.view.matrix = originalmatrix;
7252
7253         CHECKGLERROR
7254 }
7255
7256 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7257 {
7258         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7259         {
7260                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7261                 if (r_timereport_active)
7262                         R_TimeReport("waterworld");
7263         }
7264
7265         // don't let sound skip if going slow
7266         if (r_refdef.scene.extraupdate)
7267                 S_ExtraUpdate ();
7268
7269         R_DrawModelsAddWaterPlanes();
7270         if (r_timereport_active)
7271                 R_TimeReport("watermodels");
7272
7273         if (r_fb.water.numwaterplanes)
7274         {
7275                 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7276                 if (r_timereport_active)
7277                         R_TimeReport("waterscenes");
7278         }
7279 }
7280
7281 extern cvar_t cl_locs_show;
7282 static void R_DrawLocs(void);
7283 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7284 static void R_DrawModelDecals(void);
7285 extern cvar_t cl_decals_newsystem;
7286 extern qboolean r_shadow_usingdeferredprepass;
7287 extern int r_shadow_shadowmapatlas_modelshadows_size;
7288 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7289 {
7290         qboolean shadowmapping = false;
7291
7292         if (r_timereport_active)
7293                 R_TimeReport("beginscene");
7294
7295         r_refdef.stats[r_stat_renders]++;
7296
7297         R_UpdateFog();
7298
7299         // don't let sound skip if going slow
7300         if (r_refdef.scene.extraupdate)
7301                 S_ExtraUpdate ();
7302
7303         R_MeshQueue_BeginScene();
7304
7305         R_SkyStartFrame();
7306
7307         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);
7308
7309         if (r_timereport_active)
7310                 R_TimeReport("skystartframe");
7311
7312         if (cl.csqc_vidvars.drawworld)
7313         {
7314                 // don't let sound skip if going slow
7315                 if (r_refdef.scene.extraupdate)
7316                         S_ExtraUpdate ();
7317
7318                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7319                 {
7320                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7321                         if (r_timereport_active)
7322                                 R_TimeReport("worldsky");
7323                 }
7324
7325                 if (R_DrawBrushModelsSky() && r_timereport_active)
7326                         R_TimeReport("bmodelsky");
7327
7328                 if (skyrendermasked && skyrenderlater)
7329                 {
7330                         // we have to force off the water clipping plane while rendering sky
7331                         R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7332                         R_Sky();
7333                         R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7334                         if (r_timereport_active)
7335                                 R_TimeReport("sky");
7336                 }
7337         }
7338
7339         // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7340         r_shadow_viewfbo = viewfbo;
7341         r_shadow_viewdepthtexture = viewdepthtexture;
7342         r_shadow_viewcolortexture = viewcolortexture;
7343         r_shadow_viewx = viewx;
7344         r_shadow_viewy = viewy;
7345         r_shadow_viewwidth = viewwidth;
7346         r_shadow_viewheight = viewheight;
7347
7348         R_Shadow_PrepareModelShadows();
7349         R_Shadow_PrepareLights();
7350         if (r_timereport_active)
7351                 R_TimeReport("preparelights");
7352
7353         // render all the shadowmaps that will be used for this view
7354         shadowmapping = R_Shadow_ShadowMappingEnabled();
7355         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7356         {
7357                 R_Shadow_DrawShadowMaps();
7358                 if (r_timereport_active)
7359                         R_TimeReport("shadowmaps");
7360         }
7361
7362         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7363         if (r_shadow_usingdeferredprepass)
7364                 R_Shadow_DrawPrepass();
7365
7366         // now we begin the forward pass of the view render
7367         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7368         {
7369                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7370                 if (r_timereport_active)
7371                         R_TimeReport("worlddepth");
7372         }
7373         if (r_depthfirst.integer >= 2)
7374         {
7375                 R_DrawModelsDepth();
7376                 if (r_timereport_active)
7377                         R_TimeReport("modeldepth");
7378         }
7379
7380         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7381         {
7382                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7383                 if (r_timereport_active)
7384                         R_TimeReport("world");
7385         }
7386
7387         // don't let sound skip if going slow
7388         if (r_refdef.scene.extraupdate)
7389                 S_ExtraUpdate ();
7390
7391         R_DrawModels();
7392         if (r_timereport_active)
7393                 R_TimeReport("models");
7394
7395         // don't let sound skip if going slow
7396         if (r_refdef.scene.extraupdate)
7397                 S_ExtraUpdate ();
7398
7399         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7400         {
7401                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7402                 R_Shadow_DrawModelShadows();
7403                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7404                 // don't let sound skip if going slow
7405                 if (r_refdef.scene.extraupdate)
7406                         S_ExtraUpdate ();
7407         }
7408
7409         if (!r_shadow_usingdeferredprepass)
7410         {
7411                 R_Shadow_DrawLights();
7412                 if (r_timereport_active)
7413                         R_TimeReport("rtlights");
7414         }
7415
7416         // don't let sound skip if going slow
7417         if (r_refdef.scene.extraupdate)
7418                 S_ExtraUpdate ();
7419
7420         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7421         {
7422                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7423                 R_Shadow_DrawModelShadows();
7424                 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7425                 // don't let sound skip if going slow
7426                 if (r_refdef.scene.extraupdate)
7427                         S_ExtraUpdate ();
7428         }
7429
7430         if (cl.csqc_vidvars.drawworld)
7431         {
7432                 if (cl_decals_newsystem.integer)
7433                 {
7434                         R_DrawModelDecals();
7435                         if (r_timereport_active)
7436                                 R_TimeReport("modeldecals");
7437                 }
7438                 else
7439                 {
7440                         R_DrawDecals();
7441                         if (r_timereport_active)
7442                                 R_TimeReport("decals");
7443                 }
7444
7445                 R_DrawParticles();
7446                 if (r_timereport_active)
7447                         R_TimeReport("particles");
7448
7449                 R_DrawExplosions();
7450                 if (r_timereport_active)
7451                         R_TimeReport("explosions");
7452         }
7453
7454         if (r_refdef.view.showdebug)
7455         {
7456                 if (cl_locs_show.integer)
7457                 {
7458                         R_DrawLocs();
7459                         if (r_timereport_active)
7460                                 R_TimeReport("showlocs");
7461                 }
7462
7463                 if (r_drawportals.integer)
7464                 {
7465                         R_DrawPortals();
7466                         if (r_timereport_active)
7467                                 R_TimeReport("portals");
7468                 }
7469
7470                 if (r_showbboxes_client.value > 0)
7471                 {
7472                         R_DrawEntityBBoxes(CLVM_prog);
7473                         if (r_timereport_active)
7474                                 R_TimeReport("clbboxes");
7475                 }
7476                 if (r_showbboxes.value > 0)
7477                 {
7478                         R_DrawEntityBBoxes(SVVM_prog);
7479                         if (r_timereport_active)
7480                                 R_TimeReport("svbboxes");
7481                 }
7482         }
7483
7484         if (r_transparent.integer)
7485         {
7486                 R_MeshQueue_RenderTransparent();
7487                 if (r_timereport_active)
7488                         R_TimeReport("drawtrans");
7489         }
7490
7491         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))
7492         {
7493                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7494                 if (r_timereport_active)
7495                         R_TimeReport("worlddebug");
7496                 R_DrawModelsDebug();
7497                 if (r_timereport_active)
7498                         R_TimeReport("modeldebug");
7499         }
7500
7501         if (cl.csqc_vidvars.drawworld)
7502         {
7503                 R_Shadow_DrawCoronas();
7504                 if (r_timereport_active)
7505                         R_TimeReport("coronas");
7506         }
7507
7508 #if 0
7509         {
7510                 GL_DepthTest(false);
7511                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7512                 GL_Color(1, 1, 1, 1);
7513                 qglBegin(GL_POLYGON);
7514                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7515                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7516                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7517                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7518                 qglEnd();
7519                 qglBegin(GL_POLYGON);
7520                 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]);
7521                 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]);
7522                 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]);
7523                 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]);
7524                 qglEnd();
7525                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7526         }
7527 #endif
7528
7529         // don't let sound skip if going slow
7530         if (r_refdef.scene.extraupdate)
7531                 S_ExtraUpdate ();
7532 }
7533
7534 static const unsigned short bboxelements[36] =
7535 {
7536         5, 1, 3, 5, 3, 7,
7537         6, 2, 0, 6, 0, 4,
7538         7, 3, 2, 7, 2, 6,
7539         4, 0, 1, 4, 1, 5,
7540         4, 5, 7, 4, 7, 6,
7541         1, 0, 2, 1, 2, 3,
7542 };
7543
7544 #define BBOXEDGES 13
7545 static const float bboxedges[BBOXEDGES][6] = 
7546 {
7547         // whole box
7548         { 0, 0, 0, 1, 1, 1 },
7549         // bottom edges
7550         { 0, 0, 0, 0, 1, 0 },
7551         { 0, 0, 0, 1, 0, 0 },
7552         { 0, 1, 0, 1, 1, 0 },
7553         { 1, 0, 0, 1, 1, 0 },
7554         // top edges
7555         { 0, 0, 1, 0, 1, 1 },
7556         { 0, 0, 1, 1, 0, 1 },
7557         { 0, 1, 1, 1, 1, 1 },
7558         { 1, 0, 1, 1, 1, 1 },
7559         // vertical edges
7560         { 0, 0, 0, 0, 0, 1 },
7561         { 1, 0, 0, 1, 0, 1 },
7562         { 0, 1, 0, 0, 1, 1 },
7563         { 1, 1, 0, 1, 1, 1 },
7564 };
7565
7566 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7567 {
7568         int numvertices = BBOXEDGES * 8;
7569         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7570         int numtriangles = BBOXEDGES * 12;
7571         unsigned short elements[BBOXEDGES * 36];
7572         int i, edge;
7573         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7574
7575         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7576
7577         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7578         GL_DepthMask(false);
7579         GL_DepthRange(0, 1);
7580         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7581
7582         for (edge = 0; edge < BBOXEDGES; edge++)
7583         {
7584                 for (i = 0; i < 3; i++)
7585                 {
7586                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7587                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7588                 }
7589                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7590                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7591                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7592                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7593                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7594                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7595                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7596                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7597                 for (i = 0; i < 36; i++)
7598                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7599         }
7600         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7601         if (r_refdef.fogenabled)
7602         {
7603                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7604                 {
7605                         f1 = RSurf_FogVertex(v);
7606                         f2 = 1 - f1;
7607                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7608                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7609                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7610                 }
7611         }
7612         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7613         R_Mesh_ResetTextureState();
7614         R_SetupShader_Generic_NoTexture(false, false);
7615         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7616 }
7617
7618 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7619 {
7620         // hacky overloading of the parameters
7621         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7622         int i;
7623         float color[4];
7624         prvm_edict_t *edict;
7625
7626         GL_CullFace(GL_NONE);
7627         R_SetupShader_Generic_NoTexture(false, false);
7628
7629         for (i = 0;i < numsurfaces;i++)
7630         {
7631                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7632                 switch ((int)PRVM_serveredictfloat(edict, solid))
7633                 {
7634                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7635                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7636                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7637                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7638                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7639                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7640                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7641                 }
7642                 if (prog == CLVM_prog)
7643                         color[3] *= r_showbboxes_client.value;
7644                 else
7645                         color[3] *= r_showbboxes.value;
7646                 color[3] = bound(0, color[3], 1);
7647                 GL_DepthTest(!r_showdisabledepthtest.integer);
7648                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7649         }
7650 }
7651
7652 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7653 {
7654         int i;
7655         prvm_edict_t *edict;
7656         vec3_t center;
7657
7658         if (prog == NULL)
7659                 return;
7660
7661         for (i = 0; i < prog->num_edicts; i++)
7662         {
7663                 edict = PRVM_EDICT_NUM(i);
7664                 if (edict->priv.server->free)
7665                         continue;
7666                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7667                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7668                         continue;
7669                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7670                         continue;
7671                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7672                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7673         }
7674 }
7675
7676 static const int nomodelelement3i[24] =
7677 {
7678         5, 2, 0,
7679         5, 1, 2,
7680         5, 0, 3,
7681         5, 3, 1,
7682         0, 2, 4,
7683         2, 1, 4,
7684         3, 0, 4,
7685         1, 3, 4
7686 };
7687
7688 static const unsigned short nomodelelement3s[24] =
7689 {
7690         5, 2, 0,
7691         5, 1, 2,
7692         5, 0, 3,
7693         5, 3, 1,
7694         0, 2, 4,
7695         2, 1, 4,
7696         3, 0, 4,
7697         1, 3, 4
7698 };
7699
7700 static const float nomodelvertex3f[6*3] =
7701 {
7702         -16,   0,   0,
7703          16,   0,   0,
7704           0, -16,   0,
7705           0,  16,   0,
7706           0,   0, -16,
7707           0,   0,  16
7708 };
7709
7710 static const float nomodelcolor4f[6*4] =
7711 {
7712         0.0f, 0.0f, 0.5f, 1.0f,
7713         0.0f, 0.0f, 0.5f, 1.0f,
7714         0.0f, 0.5f, 0.0f, 1.0f,
7715         0.0f, 0.5f, 0.0f, 1.0f,
7716         0.5f, 0.0f, 0.0f, 1.0f,
7717         0.5f, 0.0f, 0.0f, 1.0f
7718 };
7719
7720 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7721 {
7722         int i;
7723         float f1, f2, *c;
7724         float color4f[6*4];
7725
7726         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);
7727
7728         // this is only called once per entity so numsurfaces is always 1, and
7729         // surfacelist is always {0}, so this code does not handle batches
7730
7731         if (rsurface.ent_flags & RENDER_ADDITIVE)
7732         {
7733                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7734                 GL_DepthMask(false);
7735         }
7736         else if (ent->alpha < 1)
7737         {
7738                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7739                 GL_DepthMask(false);
7740         }
7741         else
7742         {
7743                 GL_BlendFunc(GL_ONE, GL_ZERO);
7744                 GL_DepthMask(true);
7745         }
7746         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7747         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7748         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7749         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7750         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7751         for (i = 0, c = color4f;i < 6;i++, c += 4)
7752         {
7753                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7754                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7755                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7756                 c[3] *= ent->alpha;
7757         }
7758         if (r_refdef.fogenabled)
7759         {
7760                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7761                 {
7762                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7763                         f2 = 1 - f1;
7764                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7765                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7766                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7767                 }
7768         }
7769 //      R_Mesh_ResetTextureState();
7770         R_SetupShader_Generic_NoTexture(false, false);
7771         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7772         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7773 }
7774
7775 void R_DrawNoModel(entity_render_t *ent)
7776 {
7777         vec3_t org;
7778         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7779         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7780                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7781         else
7782                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7783 }
7784
7785 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7786 {
7787         vec3_t right1, right2, diff, normal;
7788
7789         VectorSubtract (org2, org1, normal);
7790
7791         // calculate 'right' vector for start
7792         VectorSubtract (r_refdef.view.origin, org1, diff);
7793         CrossProduct (normal, diff, right1);
7794         VectorNormalize (right1);
7795
7796         // calculate 'right' vector for end
7797         VectorSubtract (r_refdef.view.origin, org2, diff);
7798         CrossProduct (normal, diff, right2);
7799         VectorNormalize (right2);
7800
7801         vert[ 0] = org1[0] + width * right1[0];
7802         vert[ 1] = org1[1] + width * right1[1];
7803         vert[ 2] = org1[2] + width * right1[2];
7804         vert[ 3] = org1[0] - width * right1[0];
7805         vert[ 4] = org1[1] - width * right1[1];
7806         vert[ 5] = org1[2] - width * right1[2];
7807         vert[ 6] = org2[0] - width * right2[0];
7808         vert[ 7] = org2[1] - width * right2[1];
7809         vert[ 8] = org2[2] - width * right2[2];
7810         vert[ 9] = org2[0] + width * right2[0];
7811         vert[10] = org2[1] + width * right2[1];
7812         vert[11] = org2[2] + width * right2[2];
7813 }
7814
7815 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)
7816 {
7817         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7818         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7819         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7820         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7821         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7822         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7823         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7824         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7825         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7826         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7827         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7828         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7829 }
7830
7831 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7832 {
7833         int i;
7834         float *vertex3f;
7835         float v[3];
7836         VectorSet(v, x, y, z);
7837         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7838                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7839                         break;
7840         if (i == mesh->numvertices)
7841         {
7842                 if (mesh->numvertices < mesh->maxvertices)
7843                 {
7844                         VectorCopy(v, vertex3f);
7845                         mesh->numvertices++;
7846                 }
7847                 return mesh->numvertices;
7848         }
7849         else
7850                 return i;
7851 }
7852
7853 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7854 {
7855         int i;
7856         int *e, element[3];
7857         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7858         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7859         e = mesh->element3i + mesh->numtriangles * 3;
7860         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7861         {
7862                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7863                 if (mesh->numtriangles < mesh->maxtriangles)
7864                 {
7865                         *e++ = element[0];
7866                         *e++ = element[1];
7867                         *e++ = element[2];
7868                         mesh->numtriangles++;
7869                 }
7870                 element[1] = element[2];
7871         }
7872 }
7873
7874 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7875 {
7876         int i;
7877         int *e, element[3];
7878         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7879         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7880         e = mesh->element3i + mesh->numtriangles * 3;
7881         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7882         {
7883                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7884                 if (mesh->numtriangles < mesh->maxtriangles)
7885                 {
7886                         *e++ = element[0];
7887                         *e++ = element[1];
7888                         *e++ = element[2];
7889                         mesh->numtriangles++;
7890                 }
7891                 element[1] = element[2];
7892         }
7893 }
7894
7895 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7896 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7897 {
7898         int planenum, planenum2;
7899         int w;
7900         int tempnumpoints;
7901         mplane_t *plane, *plane2;
7902         double maxdist;
7903         double temppoints[2][256*3];
7904         // figure out how large a bounding box we need to properly compute this brush
7905         maxdist = 0;
7906         for (w = 0;w < numplanes;w++)
7907                 maxdist = max(maxdist, fabs(planes[w].dist));
7908         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7909         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7910         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7911         {
7912                 w = 0;
7913                 tempnumpoints = 4;
7914                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7915                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7916                 {
7917                         if (planenum2 == planenum)
7918                                 continue;
7919                         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);
7920                         w = !w;
7921                 }
7922                 if (tempnumpoints < 3)
7923                         continue;
7924                 // generate elements forming a triangle fan for this polygon
7925                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7926         }
7927 }
7928
7929 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)
7930 {
7931         texturelayer_t *layer;
7932         layer = t->currentlayers + t->currentnumlayers++;
7933         layer->type = type;
7934         layer->depthmask = depthmask;
7935         layer->blendfunc1 = blendfunc1;
7936         layer->blendfunc2 = blendfunc2;
7937         layer->texture = texture;
7938         layer->texmatrix = *matrix;
7939         layer->color[0] = r;
7940         layer->color[1] = g;
7941         layer->color[2] = b;
7942         layer->color[3] = a;
7943 }
7944
7945 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7946 {
7947         if(parms[0] == 0 && parms[1] == 0)
7948                 return false;
7949         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7950                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7951                         return false;
7952         return true;
7953 }
7954
7955 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7956 {
7957         double index, f;
7958         index = parms[2] + rsurface.shadertime * parms[3];
7959         index -= floor(index);
7960         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7961         {
7962         default:
7963         case Q3WAVEFUNC_NONE:
7964         case Q3WAVEFUNC_NOISE:
7965         case Q3WAVEFUNC_COUNT:
7966                 f = 0;
7967                 break;
7968         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7969         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7970         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7971         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7972         case Q3WAVEFUNC_TRIANGLE:
7973                 index *= 4;
7974                 f = index - floor(index);
7975                 if (index < 1)
7976                 {
7977                         // f = f;
7978                 }
7979                 else if (index < 2)
7980                         f = 1 - f;
7981                 else if (index < 3)
7982                         f = -f;
7983                 else
7984                         f = -(1 - f);
7985                 break;
7986         }
7987         f = parms[0] + parms[1] * f;
7988         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7989                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7990         return (float) f;
7991 }
7992
7993 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7994 {
7995         int w, h, idx;
7996         float shadertime;
7997         float f;
7998         float offsetd[2];
7999         float tcmat[12];
8000         matrix4x4_t matrix, temp;
8001         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8002         // it's better to have one huge fixup every 9 hours than gradual
8003         // degradation over time which looks consistently bad after many hours.
8004         //
8005         // tcmod scroll in particular suffers from this degradation which can't be
8006         // effectively worked around even with floor() tricks because we don't
8007         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8008         // a workaround involving floor() would be incorrect anyway...
8009         shadertime = rsurface.shadertime;
8010         if (shadertime >= 32768.0f)
8011                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8012         switch(tcmod->tcmod)
8013         {
8014                 case Q3TCMOD_COUNT:
8015                 case Q3TCMOD_NONE:
8016                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8017                                 matrix = r_waterscrollmatrix;
8018                         else
8019                                 matrix = identitymatrix;
8020                         break;
8021                 case Q3TCMOD_ENTITYTRANSLATE:
8022                         // this is used in Q3 to allow the gamecode to control texcoord
8023                         // scrolling on the entity, which is not supported in darkplaces yet.
8024                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8025                         break;
8026                 case Q3TCMOD_ROTATE:
8027                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8028                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8029                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8030                         break;
8031                 case Q3TCMOD_SCALE:
8032                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8033                         break;
8034                 case Q3TCMOD_SCROLL:
8035                         // this particular tcmod is a "bug for bug" compatible one with regards to
8036                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8037                         // specifically did the wrapping and so we must mimic that...
8038                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8039                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8040                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8041                         break;
8042                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8043                         w = (int) tcmod->parms[0];
8044                         h = (int) tcmod->parms[1];
8045                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8046                         f = f - floor(f);
8047                         idx = (int) floor(f * w * h);
8048                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8049                         break;
8050                 case Q3TCMOD_STRETCH:
8051                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8052                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8053                         break;
8054                 case Q3TCMOD_TRANSFORM:
8055                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8056                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8057                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8058                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8059                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8060                         break;
8061                 case Q3TCMOD_TURBULENT:
8062                         // this is handled in the RSurf_PrepareVertices function
8063                         matrix = identitymatrix;
8064                         break;
8065         }
8066         temp = *texmatrix;
8067         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8068 }
8069
8070 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8071 {
8072         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8073         char name[MAX_QPATH];
8074         skinframe_t *skinframe;
8075         unsigned char pixels[296*194];
8076         strlcpy(cache->name, skinname, sizeof(cache->name));
8077         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8078         if (developer_loading.integer)
8079                 Con_Printf("loading %s\n", name);
8080         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8081         if (!skinframe || !skinframe->base)
8082         {
8083                 unsigned char *f;
8084                 fs_offset_t filesize;
8085                 skinframe = NULL;
8086                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8087                 if (f)
8088                 {
8089                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8090                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8091                         Mem_Free(f);
8092                 }
8093         }
8094         cache->skinframe = skinframe;
8095 }
8096
8097 texture_t *R_GetCurrentTexture(texture_t *t)
8098 {
8099         int i, q;
8100         const entity_render_t *ent = rsurface.entity;
8101         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8102         q3shaderinfo_layer_tcmod_t *tcmod;
8103         float specularscale = 0.0f;
8104
8105         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8106                 return t->currentframe;
8107         t->update_lastrenderframe = r_textureframe;
8108         t->update_lastrenderentity = (void *)ent;
8109
8110         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8111                 t->camera_entity = ent->entitynumber;
8112         else
8113                 t->camera_entity = 0;
8114
8115         // switch to an alternate material if this is a q1bsp animated material
8116         {
8117                 texture_t *texture = t;
8118                 int s = rsurface.ent_skinnum;
8119                 if ((unsigned int)s >= (unsigned int)model->numskins)
8120                         s = 0;
8121                 if (model->skinscenes)
8122                 {
8123                         if (model->skinscenes[s].framecount > 1)
8124                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8125                         else
8126                                 s = model->skinscenes[s].firstframe;
8127                 }
8128                 if (s > 0)
8129                         t = t + s * model->num_surfaces;
8130                 if (t->animated)
8131                 {
8132                         // use an alternate animation if the entity's frame is not 0,
8133                         // and only if the texture has an alternate animation
8134                         if (t->animated == 2) // q2bsp
8135                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8136                         else if (rsurface.ent_alttextures && t->anim_total[1])
8137                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8138                         else
8139                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8140                 }
8141                 texture->currentframe = t;
8142         }
8143
8144         // update currentskinframe to be a qw skin or animation frame
8145         if (rsurface.ent_qwskin >= 0)
8146         {
8147                 i = rsurface.ent_qwskin;
8148                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8149                 {
8150                         r_qwskincache_size = cl.maxclients;
8151                         if (r_qwskincache)
8152                                 Mem_Free(r_qwskincache);
8153                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8154                 }
8155                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8156                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8157                 t->currentskinframe = r_qwskincache[i].skinframe;
8158                 if (t->materialshaderpass && t->currentskinframe == NULL)
8159                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8160         }
8161         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8162                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8163         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8164                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8165
8166         t->currentmaterialflags = t->basematerialflags;
8167         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8168         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8169                 t->currentalpha *= r_wateralpha.value;
8170         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8171                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8172         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8173                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8174
8175         // decide on which type of lighting to use for this surface
8176         if (rsurface.entity->render_modellight_forced)
8177                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8178         if (rsurface.entity->render_rtlight_disabled)
8179                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8180         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8181         {
8182                 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
8183                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8184                 for (q = 0; q < 3; q++)
8185                 {
8186                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8187                         t->render_modellight_lightdir[q] = q == 2;
8188                         t->render_modellight_ambient[q] = 1;
8189                         t->render_modellight_diffuse[q] = 0;
8190                         t->render_modellight_specular[q] = 0;
8191                         t->render_lightmap_ambient[q] = 0;
8192                         t->render_lightmap_diffuse[q] = 0;
8193                         t->render_lightmap_specular[q] = 0;
8194                         t->render_rtlight_diffuse[q] = 0;
8195                         t->render_rtlight_specular[q] = 0;
8196                 }
8197         }
8198         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8199         {
8200                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8201                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8202                 for (q = 0; q < 3; q++)
8203                 {
8204                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8205                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8206                         t->render_modellight_lightdir[q] = q == 2;
8207                         t->render_modellight_diffuse[q] = 0;
8208                         t->render_modellight_specular[q] = 0;
8209                         t->render_lightmap_ambient[q] = 0;
8210                         t->render_lightmap_diffuse[q] = 0;
8211                         t->render_lightmap_specular[q] = 0;
8212                         t->render_rtlight_diffuse[q] = 0;
8213                         t->render_rtlight_specular[q] = 0;
8214                 }
8215         }
8216         else if (FAKELIGHT_ENABLED)
8217         {
8218                 // no modellight if using fakelight for the map
8219                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8220                 for (q = 0; q < 3; q++)
8221                 {
8222                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8223                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8224                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8225                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8226                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8227                         t->render_lightmap_ambient[q] = 0;
8228                         t->render_lightmap_diffuse[q] = 0;
8229                         t->render_lightmap_specular[q] = 0;
8230                         t->render_rtlight_diffuse[q] = 0;
8231                         t->render_rtlight_specular[q] = 0;
8232                 }
8233         }
8234         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8235         {
8236                 // ambient + single direction light (modellight)
8237                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8238                 for (q = 0; q < 3; q++)
8239                 {
8240                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8241                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8242                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8243                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8244                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8245                         t->render_lightmap_ambient[q] = 0;
8246                         t->render_lightmap_diffuse[q] = 0;
8247                         t->render_lightmap_specular[q] = 0;
8248                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8249                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8250                 }
8251         }
8252         else
8253         {
8254                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8255                 for (q = 0; q < 3; q++)
8256                 {
8257                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8258                         t->render_modellight_lightdir[q] = q == 2;
8259                         t->render_modellight_ambient[q] = 0;
8260                         t->render_modellight_diffuse[q] = 0;
8261                         t->render_modellight_specular[q] = 0;
8262                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8263                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8264                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8265                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8266                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8267                 }
8268         }
8269
8270         if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8271         {
8272                 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8273                 // attribute, we punt it to the lightmap path and hope for the best,
8274                 // but lighting doesn't work.
8275                 //
8276                 // FIXME: this is fine for effects but CSQC polygons should be subject
8277                 // to lighting.
8278                 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8279                 for (q = 0; q < 3; q++)
8280                 {
8281                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8282                         t->render_modellight_lightdir[q] = q == 2;
8283                         t->render_modellight_ambient[q] = 0;
8284                         t->render_modellight_diffuse[q] = 0;
8285                         t->render_modellight_specular[q] = 0;
8286                         t->render_lightmap_ambient[q] = 0;
8287                         t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8288                         t->render_lightmap_specular[q] = 0;
8289                         t->render_rtlight_diffuse[q] = 0;
8290                         t->render_rtlight_specular[q] = 0;
8291                 }
8292         }
8293
8294         for (q = 0; q < 3; q++)
8295         {
8296                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8297                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8298         }
8299
8300         if (rsurface.ent_flags & RENDER_ADDITIVE)
8301                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8302         else if (t->currentalpha < 1)
8303                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8304         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8305         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8306                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8307         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8308                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8309         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8310                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8311         if (t->backgroundshaderpass)
8312                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8313         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8314         {
8315                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8316                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8317         }
8318         else
8319                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8320         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8321         {
8322                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8323                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8324         }
8325         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8326                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8327
8328         // there is no tcmod
8329         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8330         {
8331                 t->currenttexmatrix = r_waterscrollmatrix;
8332                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8333         }
8334         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8335         {
8336                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8337                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8338         }
8339
8340         if (t->materialshaderpass)
8341                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8342                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8343
8344         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8345         if (t->currentskinframe->qpixels)
8346                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8347         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8348         if (!t->basetexture)
8349                 t->basetexture = r_texture_notexture;
8350         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8351         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8352         t->nmaptexture = t->currentskinframe->nmap;
8353         if (!t->nmaptexture)
8354                 t->nmaptexture = r_texture_blanknormalmap;
8355         t->glosstexture = r_texture_black;
8356         t->glowtexture = t->currentskinframe->glow;
8357         t->fogtexture = t->currentskinframe->fog;
8358         t->reflectmasktexture = t->currentskinframe->reflect;
8359         if (t->backgroundshaderpass)
8360         {
8361                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8362                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8363                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8364                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8365                 t->backgroundglosstexture = r_texture_black;
8366                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8367                 if (!t->backgroundnmaptexture)
8368                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8369                 // make sure that if glow is going to be used, both textures are not NULL
8370                 if (!t->backgroundglowtexture && t->glowtexture)
8371                         t->backgroundglowtexture = r_texture_black;
8372                 if (!t->glowtexture && t->backgroundglowtexture)
8373                         t->glowtexture = r_texture_black;
8374         }
8375         else
8376         {
8377                 t->backgroundbasetexture = r_texture_white;
8378                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8379                 t->backgroundglosstexture = r_texture_black;
8380                 t->backgroundglowtexture = NULL;
8381         }
8382         t->specularpower = r_shadow_glossexponent.value;
8383         // TODO: store reference values for these in the texture?
8384         if (r_shadow_gloss.integer > 0)
8385         {
8386                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8387                 {
8388                         if (r_shadow_glossintensity.value > 0)
8389                         {
8390                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8391                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8392                                 specularscale = r_shadow_glossintensity.value;
8393                         }
8394                 }
8395                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8396                 {
8397                         t->glosstexture = r_texture_white;
8398                         t->backgroundglosstexture = r_texture_white;
8399                         specularscale = r_shadow_gloss2intensity.value;
8400                         t->specularpower = r_shadow_gloss2exponent.value;
8401                 }
8402         }
8403         specularscale *= t->specularscalemod;
8404         t->specularpower *= t->specularpowermod;
8405
8406         // lightmaps mode looks bad with dlights using actual texturing, so turn
8407         // off the colormap and glossmap, but leave the normalmap on as it still
8408         // accurately represents the shading involved
8409         if (gl_lightmaps.integer)
8410         {
8411                 t->basetexture = r_texture_grey128;
8412                 t->pantstexture = r_texture_black;
8413                 t->shirttexture = r_texture_black;
8414                 if (gl_lightmaps.integer < 2)
8415                         t->nmaptexture = r_texture_blanknormalmap;
8416                 t->glosstexture = r_texture_black;
8417                 t->glowtexture = NULL;
8418                 t->fogtexture = NULL;
8419                 t->reflectmasktexture = NULL;
8420                 t->backgroundbasetexture = NULL;
8421                 if (gl_lightmaps.integer < 2)
8422                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8423                 t->backgroundglosstexture = r_texture_black;
8424                 t->backgroundglowtexture = NULL;
8425                 specularscale = 0;
8426                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8427         }
8428
8429         if (specularscale != 1.0f)
8430         {
8431                 for (q = 0; q < 3; q++)
8432                 {
8433                         t->render_modellight_specular[q] *= specularscale;
8434                         t->render_lightmap_specular[q] *= specularscale;
8435                         t->render_rtlight_specular[q] *= specularscale;
8436                 }
8437         }
8438
8439         t->currentnumlayers = 0;
8440         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8441         {
8442                 int blendfunc1, blendfunc2;
8443                 qboolean depthmask;
8444                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8445                 {
8446                         blendfunc1 = GL_SRC_ALPHA;
8447                         blendfunc2 = GL_ONE;
8448                 }
8449                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8450                 {
8451                         blendfunc1 = GL_SRC_ALPHA;
8452                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8453                 }
8454                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8455                 {
8456                         blendfunc1 = t->customblendfunc[0];
8457                         blendfunc2 = t->customblendfunc[1];
8458                 }
8459                 else
8460                 {
8461                         blendfunc1 = GL_ONE;
8462                         blendfunc2 = GL_ZERO;
8463                 }
8464                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8465                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8466                 {
8467                         // basic lit geometry
8468                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8469                         // add pants/shirt if needed
8470                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8471                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8472                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8473                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8474                 }
8475                 else
8476                 {
8477                         // basic lit geometry
8478                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8479                         // add pants/shirt if needed
8480                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8481                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8482                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8483                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8484                         // now add ambient passes if needed
8485                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8486                         {
8487                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8488                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8489                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8490                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8491                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8492                         }
8493                 }
8494                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8495                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8496                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8497                 {
8498                         // if this is opaque use alpha blend which will darken the earlier
8499                         // passes cheaply.
8500                         //
8501                         // if this is an alpha blended material, all the earlier passes
8502                         // were darkened by fog already, so we only need to add the fog
8503                         // color ontop through the fog mask texture
8504                         //
8505                         // if this is an additive blended material, all the earlier passes
8506                         // were darkened by fog already, and we should not add fog color
8507                         // (because the background was not darkened, there is no fog color
8508                         // that was lost behind it).
8509                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8510                 }
8511         }
8512
8513         return t;
8514 }
8515
8516 rsurfacestate_t rsurface;
8517
8518 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8519 {
8520         dp_model_t *model = ent->model;
8521         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8522         //      return;
8523         rsurface.entity = (entity_render_t *)ent;
8524         rsurface.skeleton = ent->skeleton;
8525         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8526         rsurface.ent_skinnum = ent->skinnum;
8527         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;
8528         rsurface.ent_flags = ent->flags;
8529         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8530                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8531         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8532         rsurface.matrix = ent->matrix;
8533         rsurface.inversematrix = ent->inversematrix;
8534         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8535         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8536         R_EntityMatrix(&rsurface.matrix);
8537         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8538         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8539         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8540         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8541         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8542         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8543         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8544         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8545         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8546         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8547         if (ent->model->brush.submodel && !prepass)
8548         {
8549                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8550                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8551         }
8552         // if the animcache code decided it should use the shader path, skip the deform step
8553         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8554         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8555         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8556         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8557         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8558         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8559         {
8560                 if (ent->animcache_vertex3f)
8561                 {
8562                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8563                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8564                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8565                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8566                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8567                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8568                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8569                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8570                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8571                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8572                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8573                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8574                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8575                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8576                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8577                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8578                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8579                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8580                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8581                 }
8582                 else if (wanttangents)
8583                 {
8584                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8585                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8586                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8587                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8588                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8589                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8590                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8591                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8592                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8593                         rsurface.modelvertexmesh = NULL;
8594                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8595                         rsurface.modelvertexmesh_bufferoffset = 0;
8596                         rsurface.modelvertex3f_vertexbuffer = NULL;
8597                         rsurface.modelvertex3f_bufferoffset = 0;
8598                         rsurface.modelvertex3f_vertexbuffer = 0;
8599                         rsurface.modelvertex3f_bufferoffset = 0;
8600                         rsurface.modelsvector3f_vertexbuffer = 0;
8601                         rsurface.modelsvector3f_bufferoffset = 0;
8602                         rsurface.modeltvector3f_vertexbuffer = 0;
8603                         rsurface.modeltvector3f_bufferoffset = 0;
8604                         rsurface.modelnormal3f_vertexbuffer = 0;
8605                         rsurface.modelnormal3f_bufferoffset = 0;
8606                 }
8607                 else if (wantnormals)
8608                 {
8609                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8610                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8611                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8612                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8613                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8614                         rsurface.modelsvector3f = NULL;
8615                         rsurface.modeltvector3f = NULL;
8616                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8617                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8618                         rsurface.modelvertexmesh = NULL;
8619                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8620                         rsurface.modelvertexmesh_bufferoffset = 0;
8621                         rsurface.modelvertex3f_vertexbuffer = NULL;
8622                         rsurface.modelvertex3f_bufferoffset = 0;
8623                         rsurface.modelvertex3f_vertexbuffer = 0;
8624                         rsurface.modelvertex3f_bufferoffset = 0;
8625                         rsurface.modelsvector3f_vertexbuffer = 0;
8626                         rsurface.modelsvector3f_bufferoffset = 0;
8627                         rsurface.modeltvector3f_vertexbuffer = 0;
8628                         rsurface.modeltvector3f_bufferoffset = 0;
8629                         rsurface.modelnormal3f_vertexbuffer = 0;
8630                         rsurface.modelnormal3f_bufferoffset = 0;
8631                 }
8632                 else
8633                 {
8634                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8635                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8636                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8637                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8638                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8639                         rsurface.modelsvector3f = NULL;
8640                         rsurface.modeltvector3f = NULL;
8641                         rsurface.modelnormal3f = NULL;
8642                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8643                         rsurface.modelvertexmesh = NULL;
8644                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8645                         rsurface.modelvertexmesh_bufferoffset = 0;
8646                         rsurface.modelvertex3f_vertexbuffer = NULL;
8647                         rsurface.modelvertex3f_bufferoffset = 0;
8648                         rsurface.modelvertex3f_vertexbuffer = 0;
8649                         rsurface.modelvertex3f_bufferoffset = 0;
8650                         rsurface.modelsvector3f_vertexbuffer = 0;
8651                         rsurface.modelsvector3f_bufferoffset = 0;
8652                         rsurface.modeltvector3f_vertexbuffer = 0;
8653                         rsurface.modeltvector3f_bufferoffset = 0;
8654                         rsurface.modelnormal3f_vertexbuffer = 0;
8655                         rsurface.modelnormal3f_bufferoffset = 0;
8656                 }
8657                 rsurface.modelgeneratedvertex = true;
8658         }
8659         else
8660         {
8661                 if (rsurface.entityskeletaltransform3x4)
8662                 {
8663                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8664                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8665                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8666                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8667                 }
8668                 else
8669                 {
8670                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8671                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8672                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8673                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8674                 }
8675                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8676                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8677                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8678                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8679                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8680                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8681                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8682                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8683                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8684                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8685                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8686                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8687                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8688                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8689                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8690                 rsurface.modelgeneratedvertex = false;
8691         }
8692         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8693         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8694         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8695         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8696         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8697         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8698         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8699         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8700         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8701         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8702         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8703         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8704         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8705         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8706         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8707         rsurface.modelelement3i = model->surfmesh.data_element3i;
8708         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8709         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8710         rsurface.modelelement3s = model->surfmesh.data_element3s;
8711         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8712         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8713         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8714         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8715         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8716         rsurface.modelsurfaces = model->data_surfaces;
8717         rsurface.batchgeneratedvertex = false;
8718         rsurface.batchfirstvertex = 0;
8719         rsurface.batchnumvertices = 0;
8720         rsurface.batchfirsttriangle = 0;
8721         rsurface.batchnumtriangles = 0;
8722         rsurface.batchvertex3f  = NULL;
8723         rsurface.batchvertex3f_vertexbuffer = NULL;
8724         rsurface.batchvertex3f_bufferoffset = 0;
8725         rsurface.batchsvector3f = NULL;
8726         rsurface.batchsvector3f_vertexbuffer = NULL;
8727         rsurface.batchsvector3f_bufferoffset = 0;
8728         rsurface.batchtvector3f = NULL;
8729         rsurface.batchtvector3f_vertexbuffer = NULL;
8730         rsurface.batchtvector3f_bufferoffset = 0;
8731         rsurface.batchnormal3f  = NULL;
8732         rsurface.batchnormal3f_vertexbuffer = NULL;
8733         rsurface.batchnormal3f_bufferoffset = 0;
8734         rsurface.batchlightmapcolor4f = NULL;
8735         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8736         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8737         rsurface.batchtexcoordtexture2f = NULL;
8738         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8739         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8740         rsurface.batchtexcoordlightmap2f = NULL;
8741         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8742         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8743         rsurface.batchskeletalindex4ub = NULL;
8744         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8745         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8746         rsurface.batchskeletalweight4ub = NULL;
8747         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8748         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8749         rsurface.batchvertexmesh = NULL;
8750         rsurface.batchvertexmesh_vertexbuffer = NULL;
8751         rsurface.batchvertexmesh_bufferoffset = 0;
8752         rsurface.batchelement3i = NULL;
8753         rsurface.batchelement3i_indexbuffer = NULL;
8754         rsurface.batchelement3i_bufferoffset = 0;
8755         rsurface.batchelement3s = NULL;
8756         rsurface.batchelement3s_indexbuffer = NULL;
8757         rsurface.batchelement3s_bufferoffset = 0;
8758         rsurface.passcolor4f = NULL;
8759         rsurface.passcolor4f_vertexbuffer = NULL;
8760         rsurface.passcolor4f_bufferoffset = 0;
8761         rsurface.forcecurrenttextureupdate = false;
8762 }
8763
8764 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)
8765 {
8766         rsurface.entity = r_refdef.scene.worldentity;
8767         rsurface.skeleton = NULL;
8768         rsurface.ent_skinnum = 0;
8769         rsurface.ent_qwskin = -1;
8770         rsurface.ent_flags = entflags;
8771         rsurface.shadertime = r_refdef.scene.time - shadertime;
8772         rsurface.modelnumvertices = numvertices;
8773         rsurface.modelnumtriangles = numtriangles;
8774         rsurface.matrix = *matrix;
8775         rsurface.inversematrix = *inversematrix;
8776         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8777         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8778         R_EntityMatrix(&rsurface.matrix);
8779         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8780         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8781         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8782         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8783         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8784         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8785         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8786         rsurface.frameblend[0].lerp = 1;
8787         rsurface.ent_alttextures = false;
8788         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8789         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8790         rsurface.entityskeletaltransform3x4 = NULL;
8791         rsurface.entityskeletaltransform3x4buffer = NULL;
8792         rsurface.entityskeletaltransform3x4offset = 0;
8793         rsurface.entityskeletaltransform3x4size = 0;
8794         rsurface.entityskeletalnumtransforms = 0;
8795         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8796         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8797         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8798         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8799         if (wanttangents)
8800         {
8801                 rsurface.modelvertex3f = (float *)vertex3f;
8802                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8803                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8804                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8805         }
8806         else if (wantnormals)
8807         {
8808                 rsurface.modelvertex3f = (float *)vertex3f;
8809                 rsurface.modelsvector3f = NULL;
8810                 rsurface.modeltvector3f = NULL;
8811                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8812         }
8813         else
8814         {
8815                 rsurface.modelvertex3f = (float *)vertex3f;
8816                 rsurface.modelsvector3f = NULL;
8817                 rsurface.modeltvector3f = NULL;
8818                 rsurface.modelnormal3f = NULL;
8819         }
8820         rsurface.modelvertexmesh = NULL;
8821         rsurface.modelvertexmesh_vertexbuffer = NULL;
8822         rsurface.modelvertexmesh_bufferoffset = 0;
8823         rsurface.modelvertex3f_vertexbuffer = 0;
8824         rsurface.modelvertex3f_bufferoffset = 0;
8825         rsurface.modelsvector3f_vertexbuffer = 0;
8826         rsurface.modelsvector3f_bufferoffset = 0;
8827         rsurface.modeltvector3f_vertexbuffer = 0;
8828         rsurface.modeltvector3f_bufferoffset = 0;
8829         rsurface.modelnormal3f_vertexbuffer = 0;
8830         rsurface.modelnormal3f_bufferoffset = 0;
8831         rsurface.modelgeneratedvertex = true;
8832         rsurface.modellightmapcolor4f  = (float *)color4f;
8833         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8834         rsurface.modellightmapcolor4f_bufferoffset = 0;
8835         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8836         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8837         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8838         rsurface.modeltexcoordlightmap2f  = NULL;
8839         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8840         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8841         rsurface.modelskeletalindex4ub = NULL;
8842         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8843         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8844         rsurface.modelskeletalweight4ub = NULL;
8845         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8846         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8847         rsurface.modelelement3i = (int *)element3i;
8848         rsurface.modelelement3i_indexbuffer = NULL;
8849         rsurface.modelelement3i_bufferoffset = 0;
8850         rsurface.modelelement3s = (unsigned short *)element3s;
8851         rsurface.modelelement3s_indexbuffer = NULL;
8852         rsurface.modelelement3s_bufferoffset = 0;
8853         rsurface.modellightmapoffsets = NULL;
8854         rsurface.modelsurfaces = NULL;
8855         rsurface.batchgeneratedvertex = false;
8856         rsurface.batchfirstvertex = 0;
8857         rsurface.batchnumvertices = 0;
8858         rsurface.batchfirsttriangle = 0;
8859         rsurface.batchnumtriangles = 0;
8860         rsurface.batchvertex3f  = NULL;
8861         rsurface.batchvertex3f_vertexbuffer = NULL;
8862         rsurface.batchvertex3f_bufferoffset = 0;
8863         rsurface.batchsvector3f = NULL;
8864         rsurface.batchsvector3f_vertexbuffer = NULL;
8865         rsurface.batchsvector3f_bufferoffset = 0;
8866         rsurface.batchtvector3f = NULL;
8867         rsurface.batchtvector3f_vertexbuffer = NULL;
8868         rsurface.batchtvector3f_bufferoffset = 0;
8869         rsurface.batchnormal3f  = NULL;
8870         rsurface.batchnormal3f_vertexbuffer = NULL;
8871         rsurface.batchnormal3f_bufferoffset = 0;
8872         rsurface.batchlightmapcolor4f = NULL;
8873         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8874         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8875         rsurface.batchtexcoordtexture2f = NULL;
8876         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8877         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8878         rsurface.batchtexcoordlightmap2f = NULL;
8879         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8880         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8881         rsurface.batchskeletalindex4ub = NULL;
8882         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8883         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8884         rsurface.batchskeletalweight4ub = NULL;
8885         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8886         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8887         rsurface.batchvertexmesh = NULL;
8888         rsurface.batchvertexmesh_vertexbuffer = NULL;
8889         rsurface.batchvertexmesh_bufferoffset = 0;
8890         rsurface.batchelement3i = NULL;
8891         rsurface.batchelement3i_indexbuffer = NULL;
8892         rsurface.batchelement3i_bufferoffset = 0;
8893         rsurface.batchelement3s = NULL;
8894         rsurface.batchelement3s_indexbuffer = NULL;
8895         rsurface.batchelement3s_bufferoffset = 0;
8896         rsurface.passcolor4f = NULL;
8897         rsurface.passcolor4f_vertexbuffer = NULL;
8898         rsurface.passcolor4f_bufferoffset = 0;
8899         rsurface.forcecurrenttextureupdate = true;
8900
8901         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8902         {
8903                 if ((wantnormals || wanttangents) && !normal3f)
8904                 {
8905                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8906                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8907                 }
8908                 if (wanttangents && !svector3f)
8909                 {
8910                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8911                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8912                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8913                 }
8914         }
8915 }
8916
8917 float RSurf_FogPoint(const float *v)
8918 {
8919         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8920         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8921         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8922         float FogHeightFade = r_refdef.fogheightfade;
8923         float fogfrac;
8924         unsigned int fogmasktableindex;
8925         if (r_refdef.fogplaneviewabove)
8926                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8927         else
8928                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8929         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8930         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8931 }
8932
8933 float RSurf_FogVertex(const float *v)
8934 {
8935         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8936         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8937         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8938         float FogHeightFade = rsurface.fogheightfade;
8939         float fogfrac;
8940         unsigned int fogmasktableindex;
8941         if (r_refdef.fogplaneviewabove)
8942                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8943         else
8944                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8945         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8946         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8947 }
8948
8949 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8950 {
8951         int i;
8952         for (i = 0;i < numelements;i++)
8953                 outelement3i[i] = inelement3i[i] + adjust;
8954 }
8955
8956 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8957 extern cvar_t gl_vbo;
8958 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8959 {
8960         int deformindex;
8961         int firsttriangle;
8962         int numtriangles;
8963         int firstvertex;
8964         int endvertex;
8965         int numvertices;
8966         int surfacefirsttriangle;
8967         int surfacenumtriangles;
8968         int surfacefirstvertex;
8969         int surfaceendvertex;
8970         int surfacenumvertices;
8971         int batchnumsurfaces = texturenumsurfaces;
8972         int batchnumvertices;
8973         int batchnumtriangles;
8974         int needsupdate;
8975         int i, j;
8976         qboolean gaps;
8977         qboolean dynamicvertex;
8978         float amplitude;
8979         float animpos;
8980         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8981         float waveparms[4];
8982         unsigned char *ub;
8983         q3shaderinfo_deform_t *deform;
8984         const msurface_t *surface, *firstsurface;
8985         r_vertexmesh_t *vertexmesh;
8986         if (!texturenumsurfaces)
8987                 return;
8988         // find vertex range of this surface batch
8989         gaps = false;
8990         firstsurface = texturesurfacelist[0];
8991         firsttriangle = firstsurface->num_firsttriangle;
8992         batchnumvertices = 0;
8993         batchnumtriangles = 0;
8994         firstvertex = endvertex = firstsurface->num_firstvertex;
8995         for (i = 0;i < texturenumsurfaces;i++)
8996         {
8997                 surface = texturesurfacelist[i];
8998                 if (surface != firstsurface + i)
8999                         gaps = true;
9000                 surfacefirstvertex = surface->num_firstvertex;
9001                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9002                 surfacenumvertices = surface->num_vertices;
9003                 surfacenumtriangles = surface->num_triangles;
9004                 if (firstvertex > surfacefirstvertex)
9005                         firstvertex = surfacefirstvertex;
9006                 if (endvertex < surfaceendvertex)
9007                         endvertex = surfaceendvertex;
9008                 batchnumvertices += surfacenumvertices;
9009                 batchnumtriangles += surfacenumtriangles;
9010         }
9011
9012         r_refdef.stats[r_stat_batch_batches]++;
9013         if (gaps)
9014                 r_refdef.stats[r_stat_batch_withgaps]++;
9015         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9016         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9017         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9018
9019         // we now know the vertex range used, and if there are any gaps in it
9020         rsurface.batchfirstvertex = firstvertex;
9021         rsurface.batchnumvertices = endvertex - firstvertex;
9022         rsurface.batchfirsttriangle = firsttriangle;
9023         rsurface.batchnumtriangles = batchnumtriangles;
9024
9025         // this variable holds flags for which properties have been updated that
9026         // may require regenerating vertexmesh array...
9027         needsupdate = 0;
9028
9029         // check if any dynamic vertex processing must occur
9030         dynamicvertex = false;
9031
9032         // a cvar to force the dynamic vertex path to be taken, for debugging
9033         if (r_batch_debugdynamicvertexpath.integer)
9034         {
9035                 if (!dynamicvertex)
9036                 {
9037                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9038                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9039                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9040                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9041                 }
9042                 dynamicvertex = true;
9043         }
9044
9045         // if there is a chance of animated vertex colors, it's a dynamic batch
9046         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9047         {
9048                 if (!dynamicvertex)
9049                 {
9050                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9051                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9052                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9053                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9054                 }
9055                 dynamicvertex = true;
9056                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9057         }
9058
9059         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9060         {
9061                 switch (deform->deform)
9062                 {
9063                 default:
9064                 case Q3DEFORM_PROJECTIONSHADOW:
9065                 case Q3DEFORM_TEXT0:
9066                 case Q3DEFORM_TEXT1:
9067                 case Q3DEFORM_TEXT2:
9068                 case Q3DEFORM_TEXT3:
9069                 case Q3DEFORM_TEXT4:
9070                 case Q3DEFORM_TEXT5:
9071                 case Q3DEFORM_TEXT6:
9072                 case Q3DEFORM_TEXT7:
9073                 case Q3DEFORM_NONE:
9074                         break;
9075                 case Q3DEFORM_AUTOSPRITE:
9076                         if (!dynamicvertex)
9077                         {
9078                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9079                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9080                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9081                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9082                         }
9083                         dynamicvertex = true;
9084                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9085                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9086                         break;
9087                 case Q3DEFORM_AUTOSPRITE2:
9088                         if (!dynamicvertex)
9089                         {
9090                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9091                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9092                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9093                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9094                         }
9095                         dynamicvertex = true;
9096                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9097                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9098                         break;
9099                 case Q3DEFORM_NORMAL:
9100                         if (!dynamicvertex)
9101                         {
9102                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9103                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9104                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9105                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9106                         }
9107                         dynamicvertex = true;
9108                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9109                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9110                         break;
9111                 case Q3DEFORM_WAVE:
9112                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9113                                 break; // if wavefunc is a nop, ignore this transform
9114                         if (!dynamicvertex)
9115                         {
9116                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9117                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9118                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9119                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9120                         }
9121                         dynamicvertex = true;
9122                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9123                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9124                         break;
9125                 case Q3DEFORM_BULGE:
9126                         if (!dynamicvertex)
9127                         {
9128                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9129                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9130                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9131                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9132                         }
9133                         dynamicvertex = true;
9134                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9135                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9136                         break;
9137                 case Q3DEFORM_MOVE:
9138                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9139                                 break; // if wavefunc is a nop, ignore this transform
9140                         if (!dynamicvertex)
9141                         {
9142                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9143                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9144                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9145                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9146                         }
9147                         dynamicvertex = true;
9148                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9149                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9150                         break;
9151                 }
9152         }
9153         if (rsurface.texture->materialshaderpass)
9154         {
9155                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9156                 {
9157                 default:
9158                 case Q3TCGEN_TEXTURE:
9159                         break;
9160                 case Q3TCGEN_LIGHTMAP:
9161                         if (!dynamicvertex)
9162                         {
9163                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9164                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9165                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9166                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9167                         }
9168                         dynamicvertex = true;
9169                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9170                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9171                         break;
9172                 case Q3TCGEN_VECTOR:
9173                         if (!dynamicvertex)
9174                         {
9175                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9176                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9177                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9178                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9179                         }
9180                         dynamicvertex = true;
9181                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9182                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9183                         break;
9184                 case Q3TCGEN_ENVIRONMENT:
9185                         if (!dynamicvertex)
9186                         {
9187                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9188                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9189                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9190                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9191                         }
9192                         dynamicvertex = true;
9193                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9194                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9195                         break;
9196                 }
9197                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9198                 {
9199                         if (!dynamicvertex)
9200                         {
9201                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9202                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9203                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9204                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9205                         }
9206                         dynamicvertex = true;
9207                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9208                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9209                 }
9210         }
9211
9212         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9213         {
9214                 if (!dynamicvertex)
9215                 {
9216                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9217                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9218                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9219                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9220                 }
9221                 dynamicvertex = true;
9222                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9223         }
9224
9225         // when the model data has no vertex buffer (dynamic mesh), we need to
9226         // eliminate gaps
9227         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9228                 batchneed |= BATCHNEED_NOGAPS;
9229
9230         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9231         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9232         // we ensure this by treating the vertex batch as dynamic...
9233         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9234         {
9235                 if (!dynamicvertex)
9236                 {
9237                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9238                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9239                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9240                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9241                 }
9242                 dynamicvertex = true;
9243         }
9244
9245         if (dynamicvertex)
9246         {
9247                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9248                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9249                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9250                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9251                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9252                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9253                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9254                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9255         }
9256
9257         // if needsupdate, we have to do a dynamic vertex batch for sure
9258         if (needsupdate & batchneed)
9259         {
9260                 if (!dynamicvertex)
9261                 {
9262                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9263                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9264                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9265                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9266                 }
9267                 dynamicvertex = true;
9268         }
9269
9270         // see if we need to build vertexmesh from arrays
9271         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9272         {
9273                 if (!dynamicvertex)
9274                 {
9275                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9276                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9277                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9278                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9279                 }
9280                 dynamicvertex = true;
9281         }
9282
9283         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9284         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9285                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9286
9287         rsurface.batchvertex3f = rsurface.modelvertex3f;
9288         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9289         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9290         rsurface.batchsvector3f = rsurface.modelsvector3f;
9291         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9292         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9293         rsurface.batchtvector3f = rsurface.modeltvector3f;
9294         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9295         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9296         rsurface.batchnormal3f = rsurface.modelnormal3f;
9297         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9298         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9299         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9300         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9301         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9302         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9303         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9304         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9305         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9306         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9307         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9308         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9309         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9310         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9311         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9312         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9313         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9314         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9315         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9316         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9317         rsurface.batchelement3i = rsurface.modelelement3i;
9318         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9319         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9320         rsurface.batchelement3s = rsurface.modelelement3s;
9321         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9322         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9323         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9324         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9325         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9326         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9327         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9328
9329         // if any dynamic vertex processing has to occur in software, we copy the
9330         // entire surface list together before processing to rebase the vertices
9331         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9332         //
9333         // if any gaps exist and we do not have a static vertex buffer, we have to
9334         // copy the surface list together to avoid wasting upload bandwidth on the
9335         // vertices in the gaps.
9336         //
9337         // if gaps exist and we have a static vertex buffer, we can choose whether
9338         // to combine the index buffer ranges into one dynamic index buffer or
9339         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9340         //
9341         // in many cases the batch is reduced to one draw call.
9342
9343         rsurface.batchmultidraw = false;
9344         rsurface.batchmultidrawnumsurfaces = 0;
9345         rsurface.batchmultidrawsurfacelist = NULL;
9346
9347         if (!dynamicvertex)
9348         {
9349                 // static vertex data, just set pointers...
9350                 rsurface.batchgeneratedvertex = false;
9351                 // if there are gaps, we want to build a combined index buffer,
9352                 // otherwise use the original static buffer with an appropriate offset
9353                 if (gaps)
9354                 {
9355                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9356                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9357                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9358                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9359                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9360                         {
9361                                 rsurface.batchmultidraw = true;
9362                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9363                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9364                                 return;
9365                         }
9366                         // build a new triangle elements array for this batch
9367                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9368                         rsurface.batchfirsttriangle = 0;
9369                         numtriangles = 0;
9370                         for (i = 0;i < texturenumsurfaces;i++)
9371                         {
9372                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9373                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9374                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9375                                 numtriangles += surfacenumtriangles;
9376                         }
9377                         rsurface.batchelement3i_indexbuffer = NULL;
9378                         rsurface.batchelement3i_bufferoffset = 0;
9379                         rsurface.batchelement3s = NULL;
9380                         rsurface.batchelement3s_indexbuffer = NULL;
9381                         rsurface.batchelement3s_bufferoffset = 0;
9382                         if (endvertex <= 65536)
9383                         {
9384                                 // make a 16bit (unsigned short) index array if possible
9385                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9386                                 for (i = 0;i < numtriangles*3;i++)
9387                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9388                         }
9389                         // upload buffer data for the copytriangles batch
9390                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9391                         {
9392                                 if (rsurface.batchelement3s)
9393                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9394                                 else if (rsurface.batchelement3i)
9395                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9396                         }
9397                 }
9398                 else
9399                 {
9400                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9401                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9402                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9403                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9404                 }
9405                 return;
9406         }
9407
9408         // something needs software processing, do it for real...
9409         // we only directly handle separate array data in this case and then
9410         // generate interleaved data if needed...
9411         rsurface.batchgeneratedvertex = true;
9412         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9413         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9414         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9415         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9416
9417         // now copy the vertex data into a combined array and make an index array
9418         // (this is what Quake3 does all the time)
9419         // we also apply any skeletal animation here that would have been done in
9420         // the vertex shader, because most of the dynamic vertex animation cases
9421         // need actual vertex positions and normals
9422         //if (dynamicvertex)
9423         {
9424                 rsurface.batchvertexmesh = NULL;
9425                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9426                 rsurface.batchvertexmesh_bufferoffset = 0;
9427                 rsurface.batchvertex3f = NULL;
9428                 rsurface.batchvertex3f_vertexbuffer = NULL;
9429                 rsurface.batchvertex3f_bufferoffset = 0;
9430                 rsurface.batchsvector3f = NULL;
9431                 rsurface.batchsvector3f_vertexbuffer = NULL;
9432                 rsurface.batchsvector3f_bufferoffset = 0;
9433                 rsurface.batchtvector3f = NULL;
9434                 rsurface.batchtvector3f_vertexbuffer = NULL;
9435                 rsurface.batchtvector3f_bufferoffset = 0;
9436                 rsurface.batchnormal3f = NULL;
9437                 rsurface.batchnormal3f_vertexbuffer = NULL;
9438                 rsurface.batchnormal3f_bufferoffset = 0;
9439                 rsurface.batchlightmapcolor4f = NULL;
9440                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9441                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9442                 rsurface.batchtexcoordtexture2f = NULL;
9443                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9444                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9445                 rsurface.batchtexcoordlightmap2f = NULL;
9446                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9447                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9448                 rsurface.batchskeletalindex4ub = NULL;
9449                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9450                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9451                 rsurface.batchskeletalweight4ub = NULL;
9452                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9453                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9454                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9455                 rsurface.batchelement3i_indexbuffer = NULL;
9456                 rsurface.batchelement3i_bufferoffset = 0;
9457                 rsurface.batchelement3s = NULL;
9458                 rsurface.batchelement3s_indexbuffer = NULL;
9459                 rsurface.batchelement3s_bufferoffset = 0;
9460                 rsurface.batchskeletaltransform3x4buffer = NULL;
9461                 rsurface.batchskeletaltransform3x4offset = 0;
9462                 rsurface.batchskeletaltransform3x4size = 0;
9463                 // we'll only be setting up certain arrays as needed
9464                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9465                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9466                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9467                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9468                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9469                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9470                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9471                 {
9472                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9473                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9474                 }
9475                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9476                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9477                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9478                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9479                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9480                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9481                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9482                 {
9483                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9484                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9485                 }
9486                 numvertices = 0;
9487                 numtriangles = 0;
9488                 for (i = 0;i < texturenumsurfaces;i++)
9489                 {
9490                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9491                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9492                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9493                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9494                         // copy only the data requested
9495                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9496                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9497                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9498                         {
9499                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9500                                 {
9501                                         if (rsurface.batchvertex3f)
9502                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9503                                         else
9504                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9505                                 }
9506                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9507                                 {
9508                                         if (rsurface.modelnormal3f)
9509                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9510                                         else
9511                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9512                                 }
9513                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9514                                 {
9515                                         if (rsurface.modelsvector3f)
9516                                         {
9517                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9518                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9519                                         }
9520                                         else
9521                                         {
9522                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9523                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9524                                         }
9525                                 }
9526                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9527                                 {
9528                                         if (rsurface.modellightmapcolor4f)
9529                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9530                                         else
9531                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9532                                 }
9533                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9534                                 {
9535                                         if (rsurface.modeltexcoordtexture2f)
9536                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9537                                         else
9538                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9539                                 }
9540                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9541                                 {
9542                                         if (rsurface.modeltexcoordlightmap2f)
9543                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9544                                         else
9545                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9546                                 }
9547                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9548                                 {
9549                                         if (rsurface.modelskeletalindex4ub)
9550                                         {
9551                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9552                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9553                                         }
9554                                         else
9555                                         {
9556                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9557                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9558                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9559                                                 for (j = 0;j < surfacenumvertices;j++)
9560                                                         ub[j*4] = 255;
9561                                         }
9562                                 }
9563                         }
9564                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9565                         numvertices += surfacenumvertices;
9566                         numtriangles += surfacenumtriangles;
9567                 }
9568
9569                 // generate a 16bit index array as well if possible
9570                 // (in general, dynamic batches fit)
9571                 if (numvertices <= 65536)
9572                 {
9573                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9574                         for (i = 0;i < numtriangles*3;i++)
9575                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9576                 }
9577
9578                 // since we've copied everything, the batch now starts at 0
9579                 rsurface.batchfirstvertex = 0;
9580                 rsurface.batchnumvertices = batchnumvertices;
9581                 rsurface.batchfirsttriangle = 0;
9582                 rsurface.batchnumtriangles = batchnumtriangles;
9583         }
9584
9585         // apply skeletal animation that would have been done in the vertex shader
9586         if (rsurface.batchskeletaltransform3x4)
9587         {
9588                 const unsigned char *si;
9589                 const unsigned char *sw;
9590                 const float *t[4];
9591                 const float *b = rsurface.batchskeletaltransform3x4;
9592                 float *vp, *vs, *vt, *vn;
9593                 float w[4];
9594                 float m[3][4], n[3][4];
9595                 float tp[3], ts[3], tt[3], tn[3];
9596                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9597                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9598                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9599                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9600                 si = rsurface.batchskeletalindex4ub;
9601                 sw = rsurface.batchskeletalweight4ub;
9602                 vp = rsurface.batchvertex3f;
9603                 vs = rsurface.batchsvector3f;
9604                 vt = rsurface.batchtvector3f;
9605                 vn = rsurface.batchnormal3f;
9606                 memset(m[0], 0, sizeof(m));
9607                 memset(n[0], 0, sizeof(n));
9608                 for (i = 0;i < batchnumvertices;i++)
9609                 {
9610                         t[0] = b + si[0]*12;
9611                         if (sw[0] == 255)
9612                         {
9613                                 // common case - only one matrix
9614                                 m[0][0] = t[0][ 0];
9615                                 m[0][1] = t[0][ 1];
9616                                 m[0][2] = t[0][ 2];
9617                                 m[0][3] = t[0][ 3];
9618                                 m[1][0] = t[0][ 4];
9619                                 m[1][1] = t[0][ 5];
9620                                 m[1][2] = t[0][ 6];
9621                                 m[1][3] = t[0][ 7];
9622                                 m[2][0] = t[0][ 8];
9623                                 m[2][1] = t[0][ 9];
9624                                 m[2][2] = t[0][10];
9625                                 m[2][3] = t[0][11];
9626                         }
9627                         else if (sw[2] + sw[3])
9628                         {
9629                                 // blend 4 matrices
9630                                 t[1] = b + si[1]*12;
9631                                 t[2] = b + si[2]*12;
9632                                 t[3] = b + si[3]*12;
9633                                 w[0] = sw[0] * (1.0f / 255.0f);
9634                                 w[1] = sw[1] * (1.0f / 255.0f);
9635                                 w[2] = sw[2] * (1.0f / 255.0f);
9636                                 w[3] = sw[3] * (1.0f / 255.0f);
9637                                 // blend the matrices
9638                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9639                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9640                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9641                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9642                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9643                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9644                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9645                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9646                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9647                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9648                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9649                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9650                         }
9651                         else
9652                         {
9653                                 // blend 2 matrices
9654                                 t[1] = b + si[1]*12;
9655                                 w[0] = sw[0] * (1.0f / 255.0f);
9656                                 w[1] = sw[1] * (1.0f / 255.0f);
9657                                 // blend the matrices
9658                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9659                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9660                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9661                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9662                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9663                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9664                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9665                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9666                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9667                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9668                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9669                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9670                         }
9671                         si += 4;
9672                         sw += 4;
9673                         // modify the vertex
9674                         VectorCopy(vp, tp);
9675                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9676                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9677                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9678                         vp += 3;
9679                         if (vn)
9680                         {
9681                                 // the normal transformation matrix is a set of cross products...
9682                                 CrossProduct(m[1], m[2], n[0]);
9683                                 CrossProduct(m[2], m[0], n[1]);
9684                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9685                                 VectorCopy(vn, tn);
9686                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9687                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9688                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9689                                 VectorNormalize(vn);
9690                                 vn += 3;
9691                                 if (vs)
9692                                 {
9693                                         VectorCopy(vs, ts);
9694                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9695                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9696                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9697                                         VectorNormalize(vs);
9698                                         vs += 3;
9699                                         VectorCopy(vt, tt);
9700                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9701                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9702                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9703                                         VectorNormalize(vt);
9704                                         vt += 3;
9705                                 }
9706                         }
9707                 }
9708                 rsurface.batchskeletaltransform3x4 = NULL;
9709                 rsurface.batchskeletalnumtransforms = 0;
9710         }
9711
9712         // q1bsp surfaces rendered in vertex color mode have to have colors
9713         // calculated based on lightstyles
9714         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9715         {
9716                 // generate color arrays for the surfaces in this list
9717                 int c[4];
9718                 int scale;
9719                 int size3;
9720                 const int *offsets;
9721                 const unsigned char *lm;
9722                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9723                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9724                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9725                 numvertices = 0;
9726                 for (i = 0;i < texturenumsurfaces;i++)
9727                 {
9728                         surface = texturesurfacelist[i];
9729                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9730                         surfacenumvertices = surface->num_vertices;
9731                         if (surface->lightmapinfo->samples)
9732                         {
9733                                 for (j = 0;j < surfacenumvertices;j++)
9734                                 {
9735                                         lm = surface->lightmapinfo->samples + offsets[j];
9736                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9737                                         VectorScale(lm, scale, c);
9738                                         if (surface->lightmapinfo->styles[1] != 255)
9739                                         {
9740                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9741                                                 lm += size3;
9742                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9743                                                 VectorMA(c, scale, lm, c);
9744                                                 if (surface->lightmapinfo->styles[2] != 255)
9745                                                 {
9746                                                         lm += size3;
9747                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9748                                                         VectorMA(c, scale, lm, c);
9749                                                         if (surface->lightmapinfo->styles[3] != 255)
9750                                                         {
9751                                                                 lm += size3;
9752                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9753                                                                 VectorMA(c, scale, lm, c);
9754                                                         }
9755                                                 }
9756                                         }
9757                                         c[0] >>= 7;
9758                                         c[1] >>= 7;
9759                                         c[2] >>= 7;
9760                                         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);
9761                                         numvertices++;
9762                                 }
9763                         }
9764                         else
9765                         {
9766                                 for (j = 0;j < surfacenumvertices;j++)
9767                                 {
9768                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9769                                         numvertices++;
9770                                 }
9771                         }
9772                 }
9773         }
9774
9775         // if vertices are deformed (sprite flares and things in maps, possibly
9776         // water waves, bulges and other deformations), modify the copied vertices
9777         // in place
9778         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9779         {
9780                 float scale;
9781                 switch (deform->deform)
9782                 {
9783                 default:
9784                 case Q3DEFORM_PROJECTIONSHADOW:
9785                 case Q3DEFORM_TEXT0:
9786                 case Q3DEFORM_TEXT1:
9787                 case Q3DEFORM_TEXT2:
9788                 case Q3DEFORM_TEXT3:
9789                 case Q3DEFORM_TEXT4:
9790                 case Q3DEFORM_TEXT5:
9791                 case Q3DEFORM_TEXT6:
9792                 case Q3DEFORM_TEXT7:
9793                 case Q3DEFORM_NONE:
9794                         break;
9795                 case Q3DEFORM_AUTOSPRITE:
9796                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9797                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9798                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9799                         VectorNormalize(newforward);
9800                         VectorNormalize(newright);
9801                         VectorNormalize(newup);
9802 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9803 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9804 //                      rsurface.batchvertex3f_bufferoffset = 0;
9805 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9806 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9807 //                      rsurface.batchsvector3f_bufferoffset = 0;
9808 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9809 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9810 //                      rsurface.batchtvector3f_bufferoffset = 0;
9811 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9812 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9813 //                      rsurface.batchnormal3f_bufferoffset = 0;
9814                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9815                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9816                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9817                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9818                                 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);
9819                         // a single autosprite surface can contain multiple sprites...
9820                         for (j = 0;j < batchnumvertices - 3;j += 4)
9821                         {
9822                                 VectorClear(center);
9823                                 for (i = 0;i < 4;i++)
9824                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9825                                 VectorScale(center, 0.25f, center);
9826                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9827                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9828                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9829                                 for (i = 0;i < 4;i++)
9830                                 {
9831                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9832                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9833                                 }
9834                         }
9835                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9836                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9837                         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);
9838                         break;
9839                 case Q3DEFORM_AUTOSPRITE2:
9840                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9841                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9842                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9843                         VectorNormalize(newforward);
9844                         VectorNormalize(newright);
9845                         VectorNormalize(newup);
9846 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9847 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9848 //                      rsurface.batchvertex3f_bufferoffset = 0;
9849                         {
9850                                 const float *v1, *v2;
9851                                 vec3_t start, end;
9852                                 float f, l;
9853                                 struct
9854                                 {
9855                                         float length2;
9856                                         const float *v1;
9857                                         const float *v2;
9858                                 }
9859                                 shortest[2];
9860                                 memset(shortest, 0, sizeof(shortest));
9861                                 // a single autosprite surface can contain multiple sprites...
9862                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9863                                 {
9864                                         VectorClear(center);
9865                                         for (i = 0;i < 4;i++)
9866                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9867                                         VectorScale(center, 0.25f, center);
9868                                         // find the two shortest edges, then use them to define the
9869                                         // axis vectors for rotating around the central axis
9870                                         for (i = 0;i < 6;i++)
9871                                         {
9872                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9873                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9874                                                 l = VectorDistance2(v1, v2);
9875                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9876                                                 if (v1[2] != v2[2])
9877                                                         l += (1.0f / 1024.0f);
9878                                                 if (shortest[0].length2 > l || i == 0)
9879                                                 {
9880                                                         shortest[1] = shortest[0];
9881                                                         shortest[0].length2 = l;
9882                                                         shortest[0].v1 = v1;
9883                                                         shortest[0].v2 = v2;
9884                                                 }
9885                                                 else if (shortest[1].length2 > l || i == 1)
9886                                                 {
9887                                                         shortest[1].length2 = l;
9888                                                         shortest[1].v1 = v1;
9889                                                         shortest[1].v2 = v2;
9890                                                 }
9891                                         }
9892                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9893                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9894                                         // this calculates the right vector from the shortest edge
9895                                         // and the up vector from the edge midpoints
9896                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9897                                         VectorNormalize(right);
9898                                         VectorSubtract(end, start, up);
9899                                         VectorNormalize(up);
9900                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9901                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9902                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9903                                         VectorNegate(forward, forward);
9904                                         VectorReflect(forward, 0, up, forward);
9905                                         VectorNormalize(forward);
9906                                         CrossProduct(up, forward, newright);
9907                                         VectorNormalize(newright);
9908                                         // rotate the quad around the up axis vector, this is made
9909                                         // especially easy by the fact we know the quad is flat,
9910                                         // so we only have to subtract the center position and
9911                                         // measure distance along the right vector, and then
9912                                         // multiply that by the newright vector and add back the
9913                                         // center position
9914                                         // we also need to subtract the old position to undo the
9915                                         // displacement from the center, which we do with a
9916                                         // DotProduct, the subtraction/addition of center is also
9917                                         // optimized into DotProducts here
9918                                         l = DotProduct(right, center);
9919                                         for (i = 0;i < 4;i++)
9920                                         {
9921                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9922                                                 f = DotProduct(right, v1) - l;
9923                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9924                                         }
9925                                 }
9926                         }
9927                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9928                         {
9929 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9930 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9931 //                              rsurface.batchnormal3f_bufferoffset = 0;
9932                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9933                         }
9934                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9935                         {
9936 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9937 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9938 //                              rsurface.batchsvector3f_bufferoffset = 0;
9939 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9940 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9941 //                              rsurface.batchtvector3f_bufferoffset = 0;
9942                                 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);
9943                         }
9944                         break;
9945                 case Q3DEFORM_NORMAL:
9946                         // deform the normals to make reflections wavey
9947                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9948                         rsurface.batchnormal3f_vertexbuffer = NULL;
9949                         rsurface.batchnormal3f_bufferoffset = 0;
9950                         for (j = 0;j < batchnumvertices;j++)
9951                         {
9952                                 float vertex[3];
9953                                 float *normal = rsurface.batchnormal3f + 3*j;
9954                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9955                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9956                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9957                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9958                                 VectorNormalize(normal);
9959                         }
9960                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9961                         {
9962 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9963 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9964 //                              rsurface.batchsvector3f_bufferoffset = 0;
9965 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9966 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9967 //                              rsurface.batchtvector3f_bufferoffset = 0;
9968                                 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);
9969                         }
9970                         break;
9971                 case Q3DEFORM_WAVE:
9972                         // deform vertex array to make wavey water and flags and such
9973                         waveparms[0] = deform->waveparms[0];
9974                         waveparms[1] = deform->waveparms[1];
9975                         waveparms[2] = deform->waveparms[2];
9976                         waveparms[3] = deform->waveparms[3];
9977                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9978                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9979                         // this is how a divisor of vertex influence on deformation
9980                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9981                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9982 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9983 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9984 //                      rsurface.batchvertex3f_bufferoffset = 0;
9985 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9986 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9987 //                      rsurface.batchnormal3f_bufferoffset = 0;
9988                         for (j = 0;j < batchnumvertices;j++)
9989                         {
9990                                 // if the wavefunc depends on time, evaluate it per-vertex
9991                                 if (waveparms[3])
9992                                 {
9993                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9994                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9995                                 }
9996                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9997                         }
9998                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9999                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10000                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10001                         {
10002 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10004 //                              rsurface.batchsvector3f_bufferoffset = 0;
10005 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10006 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10007 //                              rsurface.batchtvector3f_bufferoffset = 0;
10008                                 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);
10009                         }
10010                         break;
10011                 case Q3DEFORM_BULGE:
10012                         // deform vertex array to make the surface have moving bulges
10013 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10014 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10015 //                      rsurface.batchvertex3f_bufferoffset = 0;
10016 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10017 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10018 //                      rsurface.batchnormal3f_bufferoffset = 0;
10019                         for (j = 0;j < batchnumvertices;j++)
10020                         {
10021                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10022                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10023                         }
10024                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10025                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10026                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10027                         {
10028 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10029 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10030 //                              rsurface.batchsvector3f_bufferoffset = 0;
10031 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10032 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10033 //                              rsurface.batchtvector3f_bufferoffset = 0;
10034                                 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);
10035                         }
10036                         break;
10037                 case Q3DEFORM_MOVE:
10038                         // deform vertex array
10039                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10040                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10041                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10042                         VectorScale(deform->parms, scale, waveparms);
10043 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10044 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10045 //                      rsurface.batchvertex3f_bufferoffset = 0;
10046                         for (j = 0;j < batchnumvertices;j++)
10047                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10048                         break;
10049                 }
10050         }
10051
10052         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10053         {
10054         // generate texcoords based on the chosen texcoord source
10055                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10056                 {
10057                 default:
10058                 case Q3TCGEN_TEXTURE:
10059                         break;
10060                 case Q3TCGEN_LIGHTMAP:
10061         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10062         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10063         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10064                         if (rsurface.batchtexcoordlightmap2f)
10065                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10066                         break;
10067                 case Q3TCGEN_VECTOR:
10068         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10069         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10070         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10071                         for (j = 0;j < batchnumvertices;j++)
10072                         {
10073                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10074                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10075                         }
10076                         break;
10077                 case Q3TCGEN_ENVIRONMENT:
10078                         // make environment reflections using a spheremap
10079                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10080                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10081                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10082                         for (j = 0;j < batchnumvertices;j++)
10083                         {
10084                                 // identical to Q3A's method, but executed in worldspace so
10085                                 // carried models can be shiny too
10086
10087                                 float viewer[3], d, reflected[3], worldreflected[3];
10088
10089                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10090                                 // VectorNormalize(viewer);
10091
10092                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10093
10094                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10095                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10096                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10097                                 // note: this is proportinal to viewer, so we can normalize later
10098
10099                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10100                                 VectorNormalize(worldreflected);
10101
10102                                 // note: this sphere map only uses world x and z!
10103                                 // so positive and negative y will LOOK THE SAME.
10104                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10105                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10106                         }
10107                         break;
10108                 }
10109                 // the only tcmod that needs software vertex processing is turbulent, so
10110                 // check for it here and apply the changes if needed
10111                 // and we only support that as the first one
10112                 // (handling a mixture of turbulent and other tcmods would be problematic
10113                 //  without punting it entirely to a software path)
10114                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10115                 {
10116                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10117                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10118         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10119         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10120         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10121                         for (j = 0;j < batchnumvertices;j++)
10122                         {
10123                                 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);
10124                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10125                         }
10126                 }
10127         }
10128
10129         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10130         {
10131                 // convert the modified arrays to vertex structs
10132 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10133 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10134 //              rsurface.batchvertexmesh_bufferoffset = 0;
10135                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10136                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10137                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10138                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10139                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10140                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10141                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10142                 {
10143                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10144                         {
10145                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10146                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10147                         }
10148                 }
10149                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10150                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10151                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10152                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10153                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10154                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10155                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10156                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10157                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10158                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10159                 {
10160                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10161                         {
10162                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10163                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10164                         }
10165                 }
10166         }
10167
10168         // upload buffer data for the dynamic batch
10169         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10170         {
10171                 if (rsurface.batchvertexmesh)
10172                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10173                 else
10174                 {
10175                         if (rsurface.batchvertex3f)
10176                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10177                         if (rsurface.batchsvector3f)
10178                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10179                         if (rsurface.batchtvector3f)
10180                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10181                         if (rsurface.batchnormal3f)
10182                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10183                         if (rsurface.batchlightmapcolor4f)
10184                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10185                         if (rsurface.batchtexcoordtexture2f)
10186                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10187                         if (rsurface.batchtexcoordlightmap2f)
10188                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10189                         if (rsurface.batchskeletalindex4ub)
10190                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10191                         if (rsurface.batchskeletalweight4ub)
10192                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10193                 }
10194                 if (rsurface.batchelement3s)
10195                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10196                 else if (rsurface.batchelement3i)
10197                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10198         }
10199 }
10200
10201 void RSurf_DrawBatch(void)
10202 {
10203         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10204         // through the pipeline, killing it earlier in the pipeline would have
10205         // per-surface overhead rather than per-batch overhead, so it's best to
10206         // reject it here, before it hits glDraw.
10207         if (rsurface.batchnumtriangles == 0)
10208                 return;
10209 #if 0
10210         // batch debugging code
10211         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10212         {
10213                 int i;
10214                 int j;
10215                 int c;
10216                 const int *e;
10217                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10218                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10219                 {
10220                         c = e[i];
10221                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10222                         {
10223                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10224                                 {
10225                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10226                                                 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);
10227                                         break;
10228                                 }
10229                         }
10230                 }
10231         }
10232 #endif
10233         if (rsurface.batchmultidraw)
10234         {
10235                 // issue multiple draws rather than copying index data
10236                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10237                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10238                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10239                 for (i = 0;i < numsurfaces;)
10240                 {
10241                         // combine consecutive surfaces as one draw
10242                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10243                                 if (surfacelist[j] != surfacelist[k] + 1)
10244                                         break;
10245                         firstvertex = surfacelist[i]->num_firstvertex;
10246                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10247                         firsttriangle = surfacelist[i]->num_firsttriangle;
10248                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10249                         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);
10250                         i = j;
10251                 }
10252         }
10253         else
10254         {
10255                 // there is only one consecutive run of index data (may have been combined)
10256                 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);
10257         }
10258 }
10259
10260 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10261 {
10262         // pick the closest matching water plane
10263         int planeindex, vertexindex, bestplaneindex = -1;
10264         float d, bestd;
10265         vec3_t vert;
10266         const float *v;
10267         r_waterstate_waterplane_t *p;
10268         qboolean prepared = false;
10269         bestd = 0;
10270         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10271         {
10272                 if(p->camera_entity != rsurface.texture->camera_entity)
10273                         continue;
10274                 d = 0;
10275                 if(!prepared)
10276                 {
10277                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10278                         prepared = true;
10279                         if(rsurface.batchnumvertices == 0)
10280                                 break;
10281                 }
10282                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10283                 {
10284                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10285                         d += fabs(PlaneDiff(vert, &p->plane));
10286                 }
10287                 if (bestd > d || bestplaneindex < 0)
10288                 {
10289                         bestd = d;
10290                         bestplaneindex = planeindex;
10291                 }
10292         }
10293         return bestplaneindex;
10294         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10295         // this situation though, as it might be better to render single larger
10296         // batches with useless stuff (backface culled for example) than to
10297         // render multiple smaller batches
10298 }
10299
10300 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10301 {
10302         int i;
10303         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10304         rsurface.passcolor4f_vertexbuffer = 0;
10305         rsurface.passcolor4f_bufferoffset = 0;
10306         for (i = 0;i < rsurface.batchnumvertices;i++)
10307                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10308 }
10309
10310 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10311 {
10312         int i;
10313         float f;
10314         const float *v;
10315         const float *c;
10316         float *c2;
10317         if (rsurface.passcolor4f)
10318         {
10319                 // generate color arrays
10320                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10321                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10322                 rsurface.passcolor4f_vertexbuffer = 0;
10323                 rsurface.passcolor4f_bufferoffset = 0;
10324                 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)
10325                 {
10326                         f = RSurf_FogVertex(v);
10327                         c2[0] = c[0] * f;
10328                         c2[1] = c[1] * f;
10329                         c2[2] = c[2] * f;
10330                         c2[3] = c[3];
10331                 }
10332         }
10333         else
10334         {
10335                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10336                 rsurface.passcolor4f_vertexbuffer = 0;
10337                 rsurface.passcolor4f_bufferoffset = 0;
10338                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10339                 {
10340                         f = RSurf_FogVertex(v);
10341                         c2[0] = f;
10342                         c2[1] = f;
10343                         c2[2] = f;
10344                         c2[3] = 1;
10345                 }
10346         }
10347 }
10348
10349 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10350 {
10351         int i;
10352         float f;
10353         const float *v;
10354         const float *c;
10355         float *c2;
10356         if (!rsurface.passcolor4f)
10357                 return;
10358         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10359         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10360         rsurface.passcolor4f_vertexbuffer = 0;
10361         rsurface.passcolor4f_bufferoffset = 0;
10362         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)
10363         {
10364                 f = RSurf_FogVertex(v);
10365                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10366                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10367                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10368                 c2[3] = c[3];
10369         }
10370 }
10371
10372 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10373 {
10374         int i;
10375         const float *c;
10376         float *c2;
10377         if (!rsurface.passcolor4f)
10378                 return;
10379         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10380         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10381         rsurface.passcolor4f_vertexbuffer = 0;
10382         rsurface.passcolor4f_bufferoffset = 0;
10383         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10384         {
10385                 c2[0] = c[0] * r;
10386                 c2[1] = c[1] * g;
10387                 c2[2] = c[2] * b;
10388                 c2[3] = c[3] * a;
10389         }
10390 }
10391
10392 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10393 {
10394         int i;
10395         const float *c;
10396         float *c2;
10397         if (!rsurface.passcolor4f)
10398                 return;
10399         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10400         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10401         rsurface.passcolor4f_vertexbuffer = 0;
10402         rsurface.passcolor4f_bufferoffset = 0;
10403         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10404         {
10405                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10406                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10407                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10408                 c2[3] = c[3];
10409         }
10410 }
10411
10412 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10413 {
10414         // TODO: optimize
10415         rsurface.passcolor4f = NULL;
10416         rsurface.passcolor4f_vertexbuffer = 0;
10417         rsurface.passcolor4f_bufferoffset = 0;
10418         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10419         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10420         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10421         GL_Color(r, g, b, a);
10422         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10423         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10424         R_Mesh_TexMatrix(0, NULL);
10425         RSurf_DrawBatch();
10426 }
10427
10428 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10429 {
10430         // TODO: optimize applyfog && applycolor case
10431         // just apply fog if necessary, and tint the fog color array if necessary
10432         rsurface.passcolor4f = NULL;
10433         rsurface.passcolor4f_vertexbuffer = 0;
10434         rsurface.passcolor4f_bufferoffset = 0;
10435         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10436         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10437         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10438         GL_Color(r, g, b, a);
10439         RSurf_DrawBatch();
10440 }
10441
10442 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10443 {
10444         // TODO: optimize
10445         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10446         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10447         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10448         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10449         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10450         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10451         GL_Color(r, g, b, a);
10452         RSurf_DrawBatch();
10453 }
10454
10455 static void RSurf_DrawBatch_GL11_ClampColor(void)
10456 {
10457         int i;
10458         const float *c1;
10459         float *c2;
10460         if (!rsurface.passcolor4f)
10461                 return;
10462         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10463         {
10464                 c2[0] = bound(0.0f, c1[0], 1.0f);
10465                 c2[1] = bound(0.0f, c1[1], 1.0f);
10466                 c2[2] = bound(0.0f, c1[2], 1.0f);
10467                 c2[3] = bound(0.0f, c1[3], 1.0f);
10468         }
10469 }
10470
10471 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10472 {
10473         int i;
10474         float f;
10475         const float *v;
10476         const float *n;
10477         float *c;
10478         //vec3_t eyedir;
10479
10480         // fake shading
10481         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10482         rsurface.passcolor4f_vertexbuffer = 0;
10483         rsurface.passcolor4f_bufferoffset = 0;
10484         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)
10485         {
10486                 f = -DotProduct(r_refdef.view.forward, n);
10487                 f = max(0, f);
10488                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10489                 f *= fakelightintensity;
10490                 Vector4Set(c, f, f, f, 1);
10491         }
10492 }
10493
10494 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10495 {
10496         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10497         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10498         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10499         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10500         GL_Color(r, g, b, a);
10501         RSurf_DrawBatch();
10502 }
10503
10504 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10505 {
10506         int i;
10507         float f;
10508         float alpha;
10509         const float *v;
10510         const float *n;
10511         float *c;
10512         vec3_t ambientcolor;
10513         vec3_t diffusecolor;
10514         vec3_t lightdir;
10515         // TODO: optimize
10516         // model lighting
10517         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10518         f = 0.5f * lightmapintensity;
10519         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10520         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10521         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10522         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10523         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10524         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10525         alpha = *a;
10526         if (VectorLength2(diffusecolor) > 0)
10527         {
10528                 // q3-style directional shading
10529                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10530                 rsurface.passcolor4f_vertexbuffer = 0;
10531                 rsurface.passcolor4f_bufferoffset = 0;
10532                 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)
10533                 {
10534                         if ((f = DotProduct(n, lightdir)) > 0)
10535                                 VectorMA(ambientcolor, f, diffusecolor, c);
10536                         else
10537                                 VectorCopy(ambientcolor, c);
10538                         c[3] = alpha;
10539                 }
10540                 *r = 1;
10541                 *g = 1;
10542                 *b = 1;
10543                 *a = 1;
10544                 *applycolor = false;
10545         }
10546         else
10547         {
10548                 *r = ambientcolor[0];
10549                 *g = ambientcolor[1];
10550                 *b = ambientcolor[2];
10551                 rsurface.passcolor4f = NULL;
10552                 rsurface.passcolor4f_vertexbuffer = 0;
10553                 rsurface.passcolor4f_bufferoffset = 0;
10554         }
10555 }
10556
10557 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10558 {
10559         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10560         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10561         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10562         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10563         GL_Color(r, g, b, a);
10564         RSurf_DrawBatch();
10565 }
10566
10567 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10568 {
10569         int i;
10570         float f;
10571         const float *v;
10572         float *c;
10573
10574         // fake shading
10575         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10576         rsurface.passcolor4f_vertexbuffer = 0;
10577         rsurface.passcolor4f_bufferoffset = 0;
10578
10579         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10580         {
10581                 f = 1 - RSurf_FogVertex(v);
10582                 c[0] = r;
10583                 c[1] = g;
10584                 c[2] = b;
10585                 c[3] = f * a;
10586         }
10587 }
10588
10589 void RSurf_SetupDepthAndCulling(void)
10590 {
10591         // submodels are biased to avoid z-fighting with world surfaces that they
10592         // may be exactly overlapping (avoids z-fighting artifacts on certain
10593         // doors and things in Quake maps)
10594         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10595         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10596         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10597         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10598 }
10599
10600 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10601 {
10602         int i, j;
10603         // transparent sky would be ridiculous
10604         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10605                 return;
10606         R_SetupShader_Generic_NoTexture(false, false);
10607         skyrenderlater = true;
10608         RSurf_SetupDepthAndCulling();
10609         GL_DepthMask(true);
10610
10611         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10612         if (r_sky_scissor.integer)
10613         {
10614                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10615                 for (i = 0; i < texturenumsurfaces; i++)
10616                 {
10617                         const msurface_t *surf = texturesurfacelist[i];
10618                         const float *v;
10619                         float p[3];
10620                         float mins[3], maxs[3];
10621                         int scissor[4];
10622                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10623                         {
10624                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10625                                 if (j > 0)
10626                                 {
10627                                         if (mins[0] > p[0]) mins[0] = p[0];
10628                                         if (mins[1] > p[1]) mins[1] = p[1];
10629                                         if (mins[2] > p[2]) mins[2] = p[2];
10630                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10631                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10632                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10633                                 }
10634                                 else
10635                                 {
10636                                         VectorCopy(p, mins);
10637                                         VectorCopy(p, maxs);
10638                                 }
10639                         }
10640                         if (!R_ScissorForBBox(mins, maxs, scissor))
10641                         {
10642                                 if (skyscissor[2])
10643                                 {
10644                                         if (skyscissor[0] > scissor[0])
10645                                         {
10646                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10647                                                 skyscissor[0] = scissor[0];
10648                                         }
10649                                         if (skyscissor[1] > scissor[1])
10650                                         {
10651                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10652                                                 skyscissor[1] = scissor[1];
10653                                         }
10654                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10655                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10656                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10657                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10658                                 }
10659                                 else
10660                                         Vector4Copy(scissor, skyscissor);
10661                         }
10662                 }
10663         }
10664
10665         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10666         // skymasking on them, and Quake3 never did sky masking (unlike
10667         // software Quake and software Quake2), so disable the sky masking
10668         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10669         // and skymasking also looks very bad when noclipping outside the
10670         // level, so don't use it then either.
10671         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10672         {
10673                 R_Mesh_ResetTextureState();
10674                 if (skyrendermasked)
10675                 {
10676                         R_SetupShader_DepthOrShadow(false, false, false);
10677                         // depth-only (masking)
10678                         GL_ColorMask(0, 0, 0, 0);
10679                         // just to make sure that braindead drivers don't draw
10680                         // anything despite that colormask...
10681                         GL_BlendFunc(GL_ZERO, GL_ONE);
10682                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10683                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10684                 }
10685                 else
10686                 {
10687                         R_SetupShader_Generic_NoTexture(false, false);
10688                         // fog sky
10689                         GL_BlendFunc(GL_ONE, GL_ZERO);
10690                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10691                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10692                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10693                 }
10694                 RSurf_DrawBatch();
10695                 if (skyrendermasked)
10696                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10697         }
10698         R_Mesh_ResetTextureState();
10699         GL_Color(1, 1, 1, 1);
10700 }
10701
10702 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10703 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10704 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10705 {
10706         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10707                 return;
10708         if (prepass)
10709         {
10710                 // render screenspace normalmap to texture
10711                 GL_DepthMask(true);
10712                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10713                 RSurf_DrawBatch();
10714                 return;
10715         }
10716
10717         // bind lightmap texture
10718
10719         // water/refraction/reflection/camera surfaces have to be handled specially
10720         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10721         {
10722                 int start, end, startplaneindex;
10723                 for (start = 0;start < texturenumsurfaces;start = end)
10724                 {
10725                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10726                         if(startplaneindex < 0)
10727                         {
10728                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10729                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10730                                 end = start + 1;
10731                                 continue;
10732                         }
10733                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10734                                 ;
10735                         // now that we have a batch using the same planeindex, render it
10736                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10737                         {
10738                                 // render water or distortion background
10739                                 GL_DepthMask(true);
10740                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10741                                 RSurf_DrawBatch();
10742                                 // blend surface on top
10743                                 GL_DepthMask(false);
10744                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10745                                 RSurf_DrawBatch();
10746                         }
10747                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10748                         {
10749                                 // render surface with reflection texture as input
10750                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10751                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10752                                 RSurf_DrawBatch();
10753                         }
10754                 }
10755                 return;
10756         }
10757
10758         // render surface batch normally
10759         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10760         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10761         RSurf_DrawBatch();
10762 }
10763
10764 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10765 {
10766         // OpenGL 1.3 path - anything not completely ancient
10767         qboolean applycolor;
10768         qboolean applyfog;
10769         int layerindex;
10770         const texturelayer_t *layer;
10771         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10772         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10773
10774         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10775         {
10776                 vec4_t layercolor;
10777                 int layertexrgbscale;
10778                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10779                 {
10780                         if (layerindex == 0)
10781                                 GL_AlphaTest(true);
10782                         else
10783                         {
10784                                 GL_AlphaTest(false);
10785                                 GL_DepthFunc(GL_EQUAL);
10786                         }
10787                 }
10788                 GL_DepthMask(layer->depthmask && writedepth);
10789                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10790                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10791                 {
10792                         layertexrgbscale = 4;
10793                         VectorScale(layer->color, 0.25f, layercolor);
10794                 }
10795                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10796                 {
10797                         layertexrgbscale = 2;
10798                         VectorScale(layer->color, 0.5f, layercolor);
10799                 }
10800                 else
10801                 {
10802                         layertexrgbscale = 1;
10803                         VectorScale(layer->color, 1.0f, layercolor);
10804                 }
10805                 layercolor[3] = layer->color[3];
10806                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10807                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10808                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10809                 switch (layer->type)
10810                 {
10811                 case TEXTURELAYERTYPE_LITTEXTURE:
10812                         // single-pass lightmapped texture with 2x rgbscale
10813                         R_Mesh_TexBind(0, r_texture_white);
10814                         R_Mesh_TexMatrix(0, NULL);
10815                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10816                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10817                         R_Mesh_TexBind(1, layer->texture);
10818                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10819                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10820                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10821                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10822                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10823                         else if (FAKELIGHT_ENABLED)
10824                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10825                         else if (rsurface.uselightmaptexture)
10826                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10827                         else
10828                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10829                         break;
10830                 case TEXTURELAYERTYPE_TEXTURE:
10831                         // singletexture unlit texture with transparency support
10832                         R_Mesh_TexBind(0, layer->texture);
10833                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10834                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10835                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10836                         R_Mesh_TexBind(1, 0);
10837                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10838                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10839                         break;
10840                 case TEXTURELAYERTYPE_FOG:
10841                         // singletexture fogging
10842                         if (layer->texture)
10843                         {
10844                                 R_Mesh_TexBind(0, layer->texture);
10845                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10846                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10847                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10848                         }
10849                         else
10850                         {
10851                                 R_Mesh_TexBind(0, 0);
10852                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10853                         }
10854                         R_Mesh_TexBind(1, 0);
10855                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10856                         // generate a color array for the fog pass
10857                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10858                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10859                         RSurf_DrawBatch();
10860                         break;
10861                 default:
10862                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10863                 }
10864         }
10865         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10866         {
10867                 GL_DepthFunc(GL_LEQUAL);
10868                 GL_AlphaTest(false);
10869         }
10870 }
10871
10872 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10873 {
10874         // OpenGL 1.1 - crusty old voodoo path
10875         qboolean applyfog;
10876         int layerindex;
10877         const texturelayer_t *layer;
10878         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10879         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10880
10881         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10882         {
10883                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10884                 {
10885                         if (layerindex == 0)
10886                                 GL_AlphaTest(true);
10887                         else
10888                         {
10889                                 GL_AlphaTest(false);
10890                                 GL_DepthFunc(GL_EQUAL);
10891                         }
10892                 }
10893                 GL_DepthMask(layer->depthmask && writedepth);
10894                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10895                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10896                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10897                 switch (layer->type)
10898                 {
10899                 case TEXTURELAYERTYPE_LITTEXTURE:
10900                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10901                         {
10902                                 // two-pass lit texture with 2x rgbscale
10903                                 // first the lightmap pass
10904                                 R_Mesh_TexBind(0, r_texture_white);
10905                                 R_Mesh_TexMatrix(0, NULL);
10906                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10907                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10908                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10909                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10910                                 else if (FAKELIGHT_ENABLED)
10911                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10912                                 else if (rsurface.uselightmaptexture)
10913                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10914                                 else
10915                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10916                                 // then apply the texture to it
10917                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10918                                 R_Mesh_TexBind(0, layer->texture);
10919                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10920                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10921                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10922                                 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);
10923                         }
10924                         else
10925                         {
10926                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10927                                 R_Mesh_TexBind(0, layer->texture);
10928                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10929                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10930                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10931                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10932                                         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);
10933                                 else if (FAKELIGHT_ENABLED)
10934                                         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);
10935                                 else
10936                                         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);
10937                         }
10938                         break;
10939                 case TEXTURELAYERTYPE_TEXTURE:
10940                         // singletexture unlit texture with transparency support
10941                         R_Mesh_TexBind(0, layer->texture);
10942                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10943                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10944                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10945                         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);
10946                         break;
10947                 case TEXTURELAYERTYPE_FOG:
10948                         // singletexture fogging
10949                         if (layer->texture)
10950                         {
10951                                 R_Mesh_TexBind(0, layer->texture);
10952                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10953                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10954                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10955                         }
10956                         else
10957                         {
10958                                 R_Mesh_TexBind(0, 0);
10959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10960                         }
10961                         // generate a color array for the fog pass
10962                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10963                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10964                         RSurf_DrawBatch();
10965                         break;
10966                 default:
10967                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10968                 }
10969         }
10970         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10971         {
10972                 GL_DepthFunc(GL_LEQUAL);
10973                 GL_AlphaTest(false);
10974         }
10975 }
10976
10977 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10978 {
10979         int vi;
10980         int j;
10981         r_vertexgeneric_t *batchvertex;
10982         float c[4];
10983         texture_t *t = rsurface.texture;
10984
10985 //      R_Mesh_ResetTextureState();
10986         R_SetupShader_Generic_NoTexture(false, false);
10987
10988         if(t && t->currentskinframe)
10989         {
10990                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10991                 c[3] *= t->currentalpha;
10992         }
10993         else
10994         {
10995                 c[0] = 1;
10996                 c[1] = 0;
10997                 c[2] = 1;
10998                 c[3] = 1;
10999         }
11000
11001         if (t->pantstexture || t->shirttexture)
11002         {
11003                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
11004                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
11005                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
11006         }
11007
11008         // brighten it up (as texture value 127 means "unlit")
11009         c[0] *= 2 * r_refdef.view.colorscale;
11010         c[1] *= 2 * r_refdef.view.colorscale;
11011         c[2] *= 2 * r_refdef.view.colorscale;
11012
11013         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11014                 c[3] *= r_wateralpha.value;
11015
11016         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11017         {
11018                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11019                 GL_DepthMask(false);
11020         }
11021         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
11022         {
11023                 GL_BlendFunc(GL_ONE, GL_ONE);
11024                 GL_DepthMask(false);
11025         }
11026         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11027         {
11028                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11029                 GL_DepthMask(false);
11030         }
11031         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11032         {
11033                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11034                 GL_DepthMask(false);
11035         }
11036         else
11037         {
11038                 GL_BlendFunc(GL_ONE, GL_ZERO);
11039                 GL_DepthMask(writedepth);
11040         }
11041
11042         if (r_showsurfaces.integer == 3)
11043         {
11044                 rsurface.passcolor4f = NULL;
11045
11046                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11047                 {
11048                         qboolean applycolor = true;
11049                         float one = 1.0;
11050
11051                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052
11053                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11054                 }
11055                 else if (FAKELIGHT_ENABLED)
11056                 {
11057                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11058
11059                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11060                 }
11061                 else
11062                 {
11063                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064
11065                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11066                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11067                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11068                         RSurf_DrawBatch_GL11_ApplyAmbient();
11069                 }
11070
11071                 if(!rsurface.passcolor4f)
11072                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11073
11074                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11075                 if(r_refdef.fogenabled)
11076                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11077                 RSurf_DrawBatch_GL11_ClampColor();
11078
11079                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11080                 R_SetupShader_Generic_NoTexture(false, false);
11081                 RSurf_DrawBatch();
11082         }
11083         else if (!r_refdef.view.showdebug)
11084         {
11085                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11086                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11087                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11088                 {
11089                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11090                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11091                 }
11092                 R_Mesh_PrepareVertices_Generic_Unlock();
11093                 RSurf_DrawBatch();
11094         }
11095         else if (r_showsurfaces.integer == 4)
11096         {
11097                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11098                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11099                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11100                 {
11101                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11102                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11103                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11104                 }
11105                 R_Mesh_PrepareVertices_Generic_Unlock();
11106                 RSurf_DrawBatch();
11107         }
11108         else if (r_showsurfaces.integer == 2)
11109         {
11110                 const int *e;
11111                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11112                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11113                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11114                 {
11115                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11116                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11117                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11118                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11119                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11120                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11121                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11122                 }
11123                 R_Mesh_PrepareVertices_Generic_Unlock();
11124                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11125         }
11126         else
11127         {
11128                 int texturesurfaceindex;
11129                 int k;
11130                 const msurface_t *surface;
11131                 float surfacecolor4f[4];
11132                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11133                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11134                 vi = 0;
11135                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11136                 {
11137                         surface = texturesurfacelist[texturesurfaceindex];
11138                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11139                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11140                         for (j = 0;j < surface->num_vertices;j++)
11141                         {
11142                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11143                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11144                                 vi++;
11145                         }
11146                 }
11147                 R_Mesh_PrepareVertices_Generic_Unlock();
11148                 RSurf_DrawBatch();
11149         }
11150 }
11151
11152 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11153 {
11154         CHECKGLERROR
11155         RSurf_SetupDepthAndCulling();
11156         if (r_showsurfaces.integer)
11157         {
11158                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11159                 return;
11160         }
11161         switch (vid.renderpath)
11162         {
11163         case RENDERPATH_GL20:
11164         case RENDERPATH_D3D9:
11165         case RENDERPATH_D3D10:
11166         case RENDERPATH_D3D11:
11167         case RENDERPATH_SOFT:
11168         case RENDERPATH_GLES2:
11169                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11170                 break;
11171         case RENDERPATH_GL13:
11172         case RENDERPATH_GLES1:
11173                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11174                 break;
11175         case RENDERPATH_GL11:
11176                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11177                 break;
11178         }
11179         CHECKGLERROR
11180 }
11181
11182 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11183 {
11184         int i, j;
11185         int texturenumsurfaces, endsurface;
11186         texture_t *texture;
11187         const msurface_t *surface;
11188         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11189
11190         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11191                 RSurf_ActiveModelEntity(ent, false, false, false);
11192         else
11193         {
11194                 switch (vid.renderpath)
11195                 {
11196                 case RENDERPATH_GL20:
11197                 case RENDERPATH_D3D9:
11198                 case RENDERPATH_D3D10:
11199                 case RENDERPATH_D3D11:
11200                 case RENDERPATH_SOFT:
11201                 case RENDERPATH_GLES2:
11202                         RSurf_ActiveModelEntity(ent, true, true, false);
11203                         break;
11204                 case RENDERPATH_GL11:
11205                 case RENDERPATH_GL13:
11206                 case RENDERPATH_GLES1:
11207                         RSurf_ActiveModelEntity(ent, true, false, false);
11208                         break;
11209                 }
11210         }
11211
11212         if (r_transparentdepthmasking.integer)
11213         {
11214                 qboolean setup = false;
11215                 for (i = 0;i < numsurfaces;i = j)
11216                 {
11217                         j = i + 1;
11218                         surface = rsurface.modelsurfaces + surfacelist[i];
11219                         texture = surface->texture;
11220                         rsurface.texture = R_GetCurrentTexture(texture);
11221                         rsurface.lightmaptexture = NULL;
11222                         rsurface.deluxemaptexture = NULL;
11223                         rsurface.uselightmaptexture = false;
11224                         // scan ahead until we find a different texture
11225                         endsurface = min(i + 1024, numsurfaces);
11226                         texturenumsurfaces = 0;
11227                         texturesurfacelist[texturenumsurfaces++] = surface;
11228                         for (;j < endsurface;j++)
11229                         {
11230                                 surface = rsurface.modelsurfaces + surfacelist[j];
11231                                 if (texture != surface->texture)
11232                                         break;
11233                                 texturesurfacelist[texturenumsurfaces++] = surface;
11234                         }
11235                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11236                                 continue;
11237                         // render the range of surfaces as depth
11238                         if (!setup)
11239                         {
11240                                 setup = true;
11241                                 GL_ColorMask(0,0,0,0);
11242                                 GL_Color(1,1,1,1);
11243                                 GL_DepthTest(true);
11244                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11245                                 GL_DepthMask(true);
11246 //                              R_Mesh_ResetTextureState();
11247                         }
11248                         RSurf_SetupDepthAndCulling();
11249                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11250                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11251                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11252                         RSurf_DrawBatch();
11253                 }
11254                 if (setup)
11255                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11256         }
11257
11258         for (i = 0;i < numsurfaces;i = j)
11259         {
11260                 j = i + 1;
11261                 surface = rsurface.modelsurfaces + surfacelist[i];
11262                 texture = surface->texture;
11263                 rsurface.texture = R_GetCurrentTexture(texture);
11264                 // scan ahead until we find a different texture
11265                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11266                 texturenumsurfaces = 0;
11267                 texturesurfacelist[texturenumsurfaces++] = surface;
11268                 if(FAKELIGHT_ENABLED)
11269                 {
11270                         rsurface.lightmaptexture = NULL;
11271                         rsurface.deluxemaptexture = NULL;
11272                         rsurface.uselightmaptexture = false;
11273                         for (;j < endsurface;j++)
11274                         {
11275                                 surface = rsurface.modelsurfaces + surfacelist[j];
11276                                 if (texture != surface->texture)
11277                                         break;
11278                                 texturesurfacelist[texturenumsurfaces++] = surface;
11279                         }
11280                 }
11281                 else
11282                 {
11283                         rsurface.lightmaptexture = surface->lightmaptexture;
11284                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11285                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11286                         for (;j < endsurface;j++)
11287                         {
11288                                 surface = rsurface.modelsurfaces + surfacelist[j];
11289                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11290                                         break;
11291                                 texturesurfacelist[texturenumsurfaces++] = surface;
11292                         }
11293                 }
11294                 // render the range of surfaces
11295                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11296         }
11297         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11298 }
11299
11300 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11301 {
11302         // transparent surfaces get pushed off into the transparent queue
11303         int surfacelistindex;
11304         const msurface_t *surface;
11305         vec3_t tempcenter, center;
11306         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11307         {
11308                 surface = texturesurfacelist[surfacelistindex];
11309                 if (r_transparent_sortsurfacesbynearest.integer)
11310                 {
11311                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11312                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11313                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11314                 }
11315                 else
11316                 {
11317                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11318                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11319                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11320                 }
11321                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11322                 if (rsurface.entity->transparent_offset) // transparent offset
11323                 {
11324                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11325                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11326                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11327                 }
11328                 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);
11329         }
11330 }
11331
11332 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11333 {
11334         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11335                 return;
11336         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11337                 return;
11338         RSurf_SetupDepthAndCulling();
11339         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11340         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11341         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11342         RSurf_DrawBatch();
11343 }
11344
11345 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11346 {
11347         CHECKGLERROR
11348         if (depthonly)
11349                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11350         else if (prepass)
11351         {
11352                 if (!rsurface.texture->currentnumlayers)
11353                         return;
11354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11355                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11356                 else
11357                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11358         }
11359         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11360                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11361         else if (!rsurface.texture->currentnumlayers)
11362                 return;
11363         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11364         {
11365                 // in the deferred case, transparent surfaces were queued during prepass
11366                 if (!r_shadow_usingdeferredprepass)
11367                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11368         }
11369         else
11370         {
11371                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11372                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11373         }
11374         CHECKGLERROR
11375 }
11376
11377 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11378 {
11379         int i, j;
11380         texture_t *texture;
11381         R_FrameData_SetMark();
11382         // break the surface list down into batches by texture and use of lightmapping
11383         for (i = 0;i < numsurfaces;i = j)
11384         {
11385                 j = i + 1;
11386                 // texture is the base texture pointer, rsurface.texture is the
11387                 // current frame/skin the texture is directing us to use (for example
11388                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11389                 // use skin 1 instead)
11390                 texture = surfacelist[i]->texture;
11391                 rsurface.texture = R_GetCurrentTexture(texture);
11392                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11393                 {
11394                         // if this texture is not the kind we want, skip ahead to the next one
11395                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11396                                 ;
11397                         continue;
11398                 }
11399                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11400                 {
11401                         rsurface.lightmaptexture = NULL;
11402                         rsurface.deluxemaptexture = NULL;
11403                         rsurface.uselightmaptexture = false;
11404                         // simply scan ahead until we find a different texture or lightmap state
11405                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11406                                 ;
11407                 }
11408                 else
11409                 {
11410                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11411                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11412                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11413                         // simply scan ahead until we find a different texture or lightmap state
11414                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11415                                 ;
11416                 }
11417                 // render the range of surfaces
11418                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11419         }
11420         R_FrameData_ReturnToMark();
11421 }
11422
11423 float locboxvertex3f[6*4*3] =
11424 {
11425         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11426         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11427         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11428         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11429         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11430         1,0,0, 0,0,0, 0,1,0, 1,1,0
11431 };
11432
11433 unsigned short locboxelements[6*2*3] =
11434 {
11435          0, 1, 2, 0, 2, 3,
11436          4, 5, 6, 4, 6, 7,
11437          8, 9,10, 8,10,11,
11438         12,13,14, 12,14,15,
11439         16,17,18, 16,18,19,
11440         20,21,22, 20,22,23
11441 };
11442
11443 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11444 {
11445         int i, j;
11446         cl_locnode_t *loc = (cl_locnode_t *)ent;
11447         vec3_t mins, size;
11448         float vertex3f[6*4*3];
11449         CHECKGLERROR
11450         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11451         GL_DepthMask(false);
11452         GL_DepthRange(0, 1);
11453         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11454         GL_DepthTest(true);
11455         GL_CullFace(GL_NONE);
11456         R_EntityMatrix(&identitymatrix);
11457
11458 //      R_Mesh_ResetTextureState();
11459
11460         i = surfacelist[0];
11461         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11462                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11463                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11464                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11465
11466         if (VectorCompare(loc->mins, loc->maxs))
11467         {
11468                 VectorSet(size, 2, 2, 2);
11469                 VectorMA(loc->mins, -0.5f, size, mins);
11470         }
11471         else
11472         {
11473                 VectorCopy(loc->mins, mins);
11474                 VectorSubtract(loc->maxs, loc->mins, size);
11475         }
11476
11477         for (i = 0;i < 6*4*3;)
11478                 for (j = 0;j < 3;j++, i++)
11479                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11480
11481         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11482         R_SetupShader_Generic_NoTexture(false, false);
11483         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11484 }
11485
11486 void R_DrawLocs(void)
11487 {
11488         int index;
11489         cl_locnode_t *loc, *nearestloc;
11490         vec3_t center;
11491         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11492         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11493         {
11494                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11495                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11496         }
11497 }
11498
11499 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11500 {
11501         if (decalsystem->decals)
11502                 Mem_Free(decalsystem->decals);
11503         memset(decalsystem, 0, sizeof(*decalsystem));
11504 }
11505
11506 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)
11507 {
11508         tridecal_t *decal;
11509         tridecal_t *decals;
11510         int i;
11511
11512         // expand or initialize the system
11513         if (decalsystem->maxdecals <= decalsystem->numdecals)
11514         {
11515                 decalsystem_t old = *decalsystem;
11516                 qboolean useshortelements;
11517                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11518                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11519                 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)));
11520                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11521                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11522                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11523                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11524                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11525                 if (decalsystem->numdecals)
11526                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11527                 if (old.decals)
11528                         Mem_Free(old.decals);
11529                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11530                         decalsystem->element3i[i] = i;
11531                 if (useshortelements)
11532                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11533                                 decalsystem->element3s[i] = i;
11534         }
11535
11536         // grab a decal and search for another free slot for the next one
11537         decals = decalsystem->decals;
11538         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11539         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11540                 ;
11541         decalsystem->freedecal = i;
11542         if (decalsystem->numdecals <= i)
11543                 decalsystem->numdecals = i + 1;
11544
11545         // initialize the decal
11546         decal->lived = 0;
11547         decal->triangleindex = triangleindex;
11548         decal->surfaceindex = surfaceindex;
11549         decal->decalsequence = decalsequence;
11550         decal->color4f[0][0] = c0[0];
11551         decal->color4f[0][1] = c0[1];
11552         decal->color4f[0][2] = c0[2];
11553         decal->color4f[0][3] = 1;
11554         decal->color4f[1][0] = c1[0];
11555         decal->color4f[1][1] = c1[1];
11556         decal->color4f[1][2] = c1[2];
11557         decal->color4f[1][3] = 1;
11558         decal->color4f[2][0] = c2[0];
11559         decal->color4f[2][1] = c2[1];
11560         decal->color4f[2][2] = c2[2];
11561         decal->color4f[2][3] = 1;
11562         decal->vertex3f[0][0] = v0[0];
11563         decal->vertex3f[0][1] = v0[1];
11564         decal->vertex3f[0][2] = v0[2];
11565         decal->vertex3f[1][0] = v1[0];
11566         decal->vertex3f[1][1] = v1[1];
11567         decal->vertex3f[1][2] = v1[2];
11568         decal->vertex3f[2][0] = v2[0];
11569         decal->vertex3f[2][1] = v2[1];
11570         decal->vertex3f[2][2] = v2[2];
11571         decal->texcoord2f[0][0] = t0[0];
11572         decal->texcoord2f[0][1] = t0[1];
11573         decal->texcoord2f[1][0] = t1[0];
11574         decal->texcoord2f[1][1] = t1[1];
11575         decal->texcoord2f[2][0] = t2[0];
11576         decal->texcoord2f[2][1] = t2[1];
11577         TriangleNormal(v0, v1, v2, decal->plane);
11578         VectorNormalize(decal->plane);
11579         decal->plane[3] = DotProduct(v0, decal->plane);
11580 }
11581
11582 extern cvar_t cl_decals_bias;
11583 extern cvar_t cl_decals_models;
11584 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11585 // baseparms, parms, temps
11586 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)
11587 {
11588         int cornerindex;
11589         int index;
11590         float v[9][3];
11591         const float *vertex3f;
11592         const float *normal3f;
11593         int numpoints;
11594         float points[2][9][3];
11595         float temp[3];
11596         float tc[9][2];
11597         float f;
11598         float c[9][4];
11599         const int *e;
11600
11601         e = rsurface.modelelement3i + 3*triangleindex;
11602
11603         vertex3f = rsurface.modelvertex3f;
11604         normal3f = rsurface.modelnormal3f;
11605
11606         if (normal3f)
11607         {
11608                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11609                 {
11610                         index = 3*e[cornerindex];
11611                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11612                 }
11613         }
11614         else
11615         {
11616                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11617                 {
11618                         index = 3*e[cornerindex];
11619                         VectorCopy(vertex3f + index, v[cornerindex]);
11620                 }
11621         }
11622
11623         // cull backfaces
11624         //TriangleNormal(v[0], v[1], v[2], normal);
11625         //if (DotProduct(normal, localnormal) < 0.0f)
11626         //      continue;
11627         // clip by each of the box planes formed from the projection matrix
11628         // if anything survives, we emit the decal
11629         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]);
11630         if (numpoints < 3)
11631                 return;
11632         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]);
11633         if (numpoints < 3)
11634                 return;
11635         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]);
11636         if (numpoints < 3)
11637                 return;
11638         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]);
11639         if (numpoints < 3)
11640                 return;
11641         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]);
11642         if (numpoints < 3)
11643                 return;
11644         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]);
11645         if (numpoints < 3)
11646                 return;
11647         // some part of the triangle survived, so we have to accept it...
11648         if (dynamic)
11649         {
11650                 // dynamic always uses the original triangle
11651                 numpoints = 3;
11652                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11653                 {
11654                         index = 3*e[cornerindex];
11655                         VectorCopy(vertex3f + index, v[cornerindex]);
11656                 }
11657         }
11658         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11659         {
11660                 // convert vertex positions to texcoords
11661                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11662                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11663                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11664                 // calculate distance fade from the projection origin
11665                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11666                 f = bound(0.0f, f, 1.0f);
11667                 c[cornerindex][0] = r * f;
11668                 c[cornerindex][1] = g * f;
11669                 c[cornerindex][2] = b * f;
11670                 c[cornerindex][3] = 1.0f;
11671                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11672         }
11673         if (dynamic)
11674                 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);
11675         else
11676                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11677                         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);
11678 }
11679 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)
11680 {
11681         matrix4x4_t projection;
11682         decalsystem_t *decalsystem;
11683         qboolean dynamic;
11684         dp_model_t *model;
11685         const msurface_t *surface;
11686         const msurface_t *surfaces;
11687         const int *surfacelist;
11688         const texture_t *texture;
11689         int numtriangles;
11690         int numsurfacelist;
11691         int surfacelistindex;
11692         int surfaceindex;
11693         int triangleindex;
11694         float localorigin[3];
11695         float localnormal[3];
11696         float localmins[3];
11697         float localmaxs[3];
11698         float localsize;
11699         //float normal[3];
11700         float planes[6][4];
11701         float angles[3];
11702         bih_t *bih;
11703         int bih_triangles_count;
11704         int bih_triangles[256];
11705         int bih_surfaces[256];
11706
11707         decalsystem = &ent->decalsystem;
11708         model = ent->model;
11709         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11710         {
11711                 R_DecalSystem_Reset(&ent->decalsystem);
11712                 return;
11713         }
11714
11715         if (!model->brush.data_leafs && !cl_decals_models.integer)
11716         {
11717                 if (decalsystem->model)
11718                         R_DecalSystem_Reset(decalsystem);
11719                 return;
11720         }
11721
11722         if (decalsystem->model != model)
11723                 R_DecalSystem_Reset(decalsystem);
11724         decalsystem->model = model;
11725
11726         RSurf_ActiveModelEntity(ent, true, false, false);
11727
11728         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11729         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11730         VectorNormalize(localnormal);
11731         localsize = worldsize*rsurface.inversematrixscale;
11732         localmins[0] = localorigin[0] - localsize;
11733         localmins[1] = localorigin[1] - localsize;
11734         localmins[2] = localorigin[2] - localsize;
11735         localmaxs[0] = localorigin[0] + localsize;
11736         localmaxs[1] = localorigin[1] + localsize;
11737         localmaxs[2] = localorigin[2] + localsize;
11738
11739         //VectorCopy(localnormal, planes[4]);
11740         //VectorVectors(planes[4], planes[2], planes[0]);
11741         AnglesFromVectors(angles, localnormal, NULL, false);
11742         AngleVectors(angles, planes[0], planes[2], planes[4]);
11743         VectorNegate(planes[0], planes[1]);
11744         VectorNegate(planes[2], planes[3]);
11745         VectorNegate(planes[4], planes[5]);
11746         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11747         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11748         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11749         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11750         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11751         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11752
11753 #if 1
11754 // works
11755 {
11756         matrix4x4_t forwardprojection;
11757         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11758         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11759 }
11760 #else
11761 // broken
11762 {
11763         float projectionvector[4][3];
11764         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11765         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11766         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11767         projectionvector[0][0] = planes[0][0] * ilocalsize;
11768         projectionvector[0][1] = planes[1][0] * ilocalsize;
11769         projectionvector[0][2] = planes[2][0] * ilocalsize;
11770         projectionvector[1][0] = planes[0][1] * ilocalsize;
11771         projectionvector[1][1] = planes[1][1] * ilocalsize;
11772         projectionvector[1][2] = planes[2][1] * ilocalsize;
11773         projectionvector[2][0] = planes[0][2] * ilocalsize;
11774         projectionvector[2][1] = planes[1][2] * ilocalsize;
11775         projectionvector[2][2] = planes[2][2] * ilocalsize;
11776         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11777         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11778         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11779         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11780 }
11781 #endif
11782
11783         dynamic = model->surfmesh.isanimated;
11784         numsurfacelist = model->nummodelsurfaces;
11785         surfacelist = model->sortedmodelsurfaces;
11786         surfaces = model->data_surfaces;
11787
11788         bih = NULL;
11789         bih_triangles_count = -1;
11790         if(!dynamic)
11791         {
11792                 if(model->render_bih.numleafs)
11793                         bih = &model->render_bih;
11794                 else if(model->collision_bih.numleafs)
11795                         bih = &model->collision_bih;
11796         }
11797         if(bih)
11798                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11799         if(bih_triangles_count == 0)
11800                 return;
11801         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11802                 return;
11803         if(bih_triangles_count > 0)
11804         {
11805                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11806                 {
11807                         surfaceindex = bih_surfaces[triangleindex];
11808                         surface = surfaces + surfaceindex;
11809                         texture = surface->texture;
11810                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11811                                 continue;
11812                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11813                                 continue;
11814                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11815                 }
11816         }
11817         else
11818         {
11819                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11820                 {
11821                         surfaceindex = surfacelist[surfacelistindex];
11822                         surface = surfaces + surfaceindex;
11823                         // check cull box first because it rejects more than any other check
11824                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11825                                 continue;
11826                         // skip transparent surfaces
11827                         texture = surface->texture;
11828                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11829                                 continue;
11830                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11831                                 continue;
11832                         numtriangles = surface->num_triangles;
11833                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11834                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11835                 }
11836         }
11837 }
11838
11839 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11840 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)
11841 {
11842         int renderentityindex;
11843         float worldmins[3];
11844         float worldmaxs[3];
11845         entity_render_t *ent;
11846
11847         if (!cl_decals_newsystem.integer)
11848                 return;
11849
11850         worldmins[0] = worldorigin[0] - worldsize;
11851         worldmins[1] = worldorigin[1] - worldsize;
11852         worldmins[2] = worldorigin[2] - worldsize;
11853         worldmaxs[0] = worldorigin[0] + worldsize;
11854         worldmaxs[1] = worldorigin[1] + worldsize;
11855         worldmaxs[2] = worldorigin[2] + worldsize;
11856
11857         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11858
11859         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11860         {
11861                 ent = r_refdef.scene.entities[renderentityindex];
11862                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11863                         continue;
11864
11865                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11866         }
11867 }
11868
11869 typedef struct r_decalsystem_splatqueue_s
11870 {
11871         vec3_t worldorigin;
11872         vec3_t worldnormal;
11873         float color[4];
11874         float tcrange[4];
11875         float worldsize;
11876         unsigned int decalsequence;
11877 }
11878 r_decalsystem_splatqueue_t;
11879
11880 int r_decalsystem_numqueued = 0;
11881 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11882
11883 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)
11884 {
11885         r_decalsystem_splatqueue_t *queue;
11886
11887         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11888                 return;
11889
11890         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11891         VectorCopy(worldorigin, queue->worldorigin);
11892         VectorCopy(worldnormal, queue->worldnormal);
11893         Vector4Set(queue->color, r, g, b, a);
11894         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11895         queue->worldsize = worldsize;
11896         queue->decalsequence = cl.decalsequence++;
11897 }
11898
11899 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11900 {
11901         int i;
11902         r_decalsystem_splatqueue_t *queue;
11903
11904         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11905                 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);
11906         r_decalsystem_numqueued = 0;
11907 }
11908
11909 extern cvar_t cl_decals_max;
11910 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11911 {
11912         int i;
11913         decalsystem_t *decalsystem = &ent->decalsystem;
11914         int numdecals;
11915         unsigned int killsequence;
11916         tridecal_t *decal;
11917         float frametime;
11918         float lifetime;
11919
11920         if (!decalsystem->numdecals)
11921                 return;
11922
11923         if (r_showsurfaces.integer)
11924                 return;
11925
11926         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11927         {
11928                 R_DecalSystem_Reset(decalsystem);
11929                 return;
11930         }
11931
11932         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11933         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11934
11935         if (decalsystem->lastupdatetime)
11936                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11937         else
11938                 frametime = 0;
11939         decalsystem->lastupdatetime = r_refdef.scene.time;
11940         numdecals = decalsystem->numdecals;
11941
11942         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11943         {
11944                 if (decal->color4f[0][3])
11945                 {
11946                         decal->lived += frametime;
11947                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11948                         {
11949                                 memset(decal, 0, sizeof(*decal));
11950                                 if (decalsystem->freedecal > i)
11951                                         decalsystem->freedecal = i;
11952                         }
11953                 }
11954         }
11955         decal = decalsystem->decals;
11956         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11957                 numdecals--;
11958
11959         // collapse the array by shuffling the tail decals into the gaps
11960         for (;;)
11961         {
11962                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11963                         decalsystem->freedecal++;
11964                 if (decalsystem->freedecal == numdecals)
11965                         break;
11966                 decal[decalsystem->freedecal] = decal[--numdecals];
11967         }
11968
11969         decalsystem->numdecals = numdecals;
11970
11971         if (numdecals <= 0)
11972         {
11973                 // if there are no decals left, reset decalsystem
11974                 R_DecalSystem_Reset(decalsystem);
11975         }
11976 }
11977
11978 extern skinframe_t *decalskinframe;
11979 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11980 {
11981         int i;
11982         decalsystem_t *decalsystem = &ent->decalsystem;
11983         int numdecals;
11984         tridecal_t *decal;
11985         float faderate;
11986         float alpha;
11987         float *v3f;
11988         float *c4f;
11989         float *t2f;
11990         const int *e;
11991         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11992         int numtris = 0;
11993
11994         numdecals = decalsystem->numdecals;
11995         if (!numdecals)
11996                 return;
11997
11998         if (r_showsurfaces.integer)
11999                 return;
12000
12001         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12002         {
12003                 R_DecalSystem_Reset(decalsystem);
12004                 return;
12005         }
12006
12007         // if the model is static it doesn't matter what value we give for
12008         // wantnormals and wanttangents, so this logic uses only rules applicable
12009         // to a model, knowing that they are meaningless otherwise
12010         RSurf_ActiveModelEntity(ent, false, false, false);
12011
12012         decalsystem->lastupdatetime = r_refdef.scene.time;
12013
12014         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12015
12016         // update vertex positions for animated models
12017         v3f = decalsystem->vertex3f;
12018         c4f = decalsystem->color4f;
12019         t2f = decalsystem->texcoord2f;
12020         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12021         {
12022                 if (!decal->color4f[0][3])
12023                         continue;
12024
12025                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12026                         continue;
12027
12028                 // skip backfaces
12029                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12030                         continue;
12031
12032                 // update color values for fading decals
12033                 if (decal->lived >= cl_decals_time.value)
12034                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12035                 else
12036                         alpha = 1.0f;
12037
12038                 c4f[ 0] = decal->color4f[0][0] * alpha;
12039                 c4f[ 1] = decal->color4f[0][1] * alpha;
12040                 c4f[ 2] = decal->color4f[0][2] * alpha;
12041                 c4f[ 3] = 1;
12042                 c4f[ 4] = decal->color4f[1][0] * alpha;
12043                 c4f[ 5] = decal->color4f[1][1] * alpha;
12044                 c4f[ 6] = decal->color4f[1][2] * alpha;
12045                 c4f[ 7] = 1;
12046                 c4f[ 8] = decal->color4f[2][0] * alpha;
12047                 c4f[ 9] = decal->color4f[2][1] * alpha;
12048                 c4f[10] = decal->color4f[2][2] * alpha;
12049                 c4f[11] = 1;
12050
12051                 t2f[0] = decal->texcoord2f[0][0];
12052                 t2f[1] = decal->texcoord2f[0][1];
12053                 t2f[2] = decal->texcoord2f[1][0];
12054                 t2f[3] = decal->texcoord2f[1][1];
12055                 t2f[4] = decal->texcoord2f[2][0];
12056                 t2f[5] = decal->texcoord2f[2][1];
12057
12058                 // update vertex positions for animated models
12059                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12060                 {
12061                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12062                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12063                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12064                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12065                 }
12066                 else
12067                 {
12068                         VectorCopy(decal->vertex3f[0], v3f);
12069                         VectorCopy(decal->vertex3f[1], v3f + 3);
12070                         VectorCopy(decal->vertex3f[2], v3f + 6);
12071                 }
12072
12073                 if (r_refdef.fogenabled)
12074                 {
12075                         alpha = RSurf_FogVertex(v3f);
12076                         VectorScale(c4f, alpha, c4f);
12077                         alpha = RSurf_FogVertex(v3f + 3);
12078                         VectorScale(c4f + 4, alpha, c4f + 4);
12079                         alpha = RSurf_FogVertex(v3f + 6);
12080                         VectorScale(c4f + 8, alpha, c4f + 8);
12081                 }
12082
12083                 v3f += 9;
12084                 c4f += 12;
12085                 t2f += 6;
12086                 numtris++;
12087         }
12088
12089         if (numtris > 0)
12090         {
12091                 r_refdef.stats[r_stat_drawndecals] += numtris;
12092
12093                 // now render the decals all at once
12094                 // (this assumes they all use one particle font texture!)
12095                 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);
12096 //              R_Mesh_ResetTextureState();
12097                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12098                 GL_DepthMask(false);
12099                 GL_DepthRange(0, 1);
12100                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12101                 GL_DepthTest(true);
12102                 GL_CullFace(GL_NONE);
12103                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12104                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12105                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12106         }
12107 }
12108
12109 static void R_DrawModelDecals(void)
12110 {
12111         int i, numdecals;
12112
12113         // fade faster when there are too many decals
12114         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12115         for (i = 0;i < r_refdef.scene.numentities;i++)
12116                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12117
12118         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12119         for (i = 0;i < r_refdef.scene.numentities;i++)
12120                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12121                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12122
12123         R_DecalSystem_ApplySplatEntitiesQueue();
12124
12125         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12126         for (i = 0;i < r_refdef.scene.numentities;i++)
12127                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12128
12129         r_refdef.stats[r_stat_totaldecals] += numdecals;
12130
12131         if (r_showsurfaces.integer)
12132                 return;
12133
12134         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12135
12136         for (i = 0;i < r_refdef.scene.numentities;i++)
12137         {
12138                 if (!r_refdef.viewcache.entityvisible[i])
12139                         continue;
12140                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12141                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12142         }
12143 }
12144
12145 extern cvar_t mod_collision_bih;
12146 static void R_DrawDebugModel(void)
12147 {
12148         entity_render_t *ent = rsurface.entity;
12149         int i, j, flagsmask;
12150         const msurface_t *surface;
12151         dp_model_t *model = ent->model;
12152
12153         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12154                 return;
12155
12156         if (r_showoverdraw.value > 0)
12157         {
12158                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12159                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12160                 R_SetupShader_Generic_NoTexture(false, false);
12161                 GL_DepthTest(false);
12162                 GL_DepthMask(false);
12163                 GL_DepthRange(0, 1);
12164                 GL_BlendFunc(GL_ONE, GL_ONE);
12165                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12166                 {
12167                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12168                                 continue;
12169                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12170                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12171                         {
12172                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12173                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12174                                 if (!rsurface.texture->currentlayers->depthmask)
12175                                         GL_Color(c, 0, 0, 1.0f);
12176                                 else if (ent == r_refdef.scene.worldentity)
12177                                         GL_Color(c, c, c, 1.0f);
12178                                 else
12179                                         GL_Color(0, c, 0, 1.0f);
12180                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12181                                 RSurf_DrawBatch();
12182                         }
12183                 }
12184                 rsurface.texture = NULL;
12185         }
12186
12187         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12188
12189 //      R_Mesh_ResetTextureState();
12190         R_SetupShader_Generic_NoTexture(false, false);
12191         GL_DepthRange(0, 1);
12192         GL_DepthTest(!r_showdisabledepthtest.integer);
12193         GL_DepthMask(false);
12194         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12195
12196         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12197         {
12198                 int triangleindex;
12199                 int bihleafindex;
12200                 qboolean cullbox = false;
12201                 const q3mbrush_t *brush;
12202                 const bih_t *bih = &model->collision_bih;
12203                 const bih_leaf_t *bihleaf;
12204                 float vertex3f[3][3];
12205                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12206                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12207                 {
12208                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12209                                 continue;
12210                         switch (bihleaf->type)
12211                         {
12212                         case BIH_BRUSH:
12213                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12214                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12215                                 {
12216                                         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);
12217                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12218                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12219                                 }
12220                                 break;
12221                         case BIH_COLLISIONTRIANGLE:
12222                                 triangleindex = bihleaf->itemindex;
12223                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12224                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12225                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12226                                 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);
12227                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12228                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12229                                 break;
12230                         case BIH_RENDERTRIANGLE:
12231                                 triangleindex = bihleaf->itemindex;
12232                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12233                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12234                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12235                                 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);
12236                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12237                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12238                                 break;
12239                         }
12240                 }
12241         }
12242
12243         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12244
12245 #ifndef USE_GLES2
12246         if (r_showtris.integer && qglPolygonMode)
12247         {
12248                 if (r_showdisabledepthtest.integer)
12249                 {
12250                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12251                         GL_DepthMask(false);
12252                 }
12253                 else
12254                 {
12255                         GL_BlendFunc(GL_ONE, GL_ZERO);
12256                         GL_DepthMask(true);
12257                 }
12258                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12259                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12260                 {
12261                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12262                                 continue;
12263                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12264                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12265                         {
12266                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12267                                 if (!rsurface.texture->currentlayers->depthmask)
12268                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12269                                 else if (ent == r_refdef.scene.worldentity)
12270                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12271                                 else
12272                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12273                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12274                                 RSurf_DrawBatch();
12275                         }
12276                 }
12277                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12278                 rsurface.texture = NULL;
12279         }
12280
12281         if (r_shownormals.value != 0 && qglBegin)
12282         {
12283                 int l, k;
12284                 vec3_t v;
12285                 if (r_showdisabledepthtest.integer)
12286                 {
12287                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12288                         GL_DepthMask(false);
12289                 }
12290                 else
12291                 {
12292                         GL_BlendFunc(GL_ONE, GL_ZERO);
12293                         GL_DepthMask(true);
12294                 }
12295                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12296                 {
12297                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12298                                 continue;
12299                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12300                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12301                         {
12302                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12303                                 qglBegin(GL_LINES);
12304                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12305                                 {
12306                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12307                                         {
12308                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12309                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12310                                                 qglVertex3f(v[0], v[1], v[2]);
12311                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12312                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12313                                                 qglVertex3f(v[0], v[1], v[2]);
12314                                         }
12315                                 }
12316                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12317                                 {
12318                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12319                                         {
12320                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12321                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12322                                                 qglVertex3f(v[0], v[1], v[2]);
12323                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12324                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12325                                                 qglVertex3f(v[0], v[1], v[2]);
12326                                         }
12327                                 }
12328                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12329                                 {
12330                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12331                                         {
12332                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12333                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12334                                                 qglVertex3f(v[0], v[1], v[2]);
12335                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12336                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12337                                                 qglVertex3f(v[0], v[1], v[2]);
12338                                         }
12339                                 }
12340                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12341                                 {
12342                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12343                                         {
12344                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12345                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12346                                                 qglVertex3f(v[0], v[1], v[2]);
12347                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12348                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12349                                                 qglVertex3f(v[0], v[1], v[2]);
12350                                         }
12351                                 }
12352                                 qglEnd();
12353                                 CHECKGLERROR
12354                         }
12355                 }
12356                 rsurface.texture = NULL;
12357         }
12358 #endif
12359 }
12360
12361 int r_maxsurfacelist = 0;
12362 const msurface_t **r_surfacelist = NULL;
12363 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12364 {
12365         int i, j, endj, flagsmask;
12366         dp_model_t *model = ent->model;
12367         msurface_t *surfaces;
12368         unsigned char *update;
12369         int numsurfacelist = 0;
12370         if (model == NULL)
12371                 return;
12372
12373         if (r_maxsurfacelist < model->num_surfaces)
12374         {
12375                 r_maxsurfacelist = model->num_surfaces;
12376                 if (r_surfacelist)
12377                         Mem_Free((msurface_t **)r_surfacelist);
12378                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12379         }
12380
12381         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12382                 RSurf_ActiveModelEntity(ent, false, false, false);
12383         else if (prepass)
12384                 RSurf_ActiveModelEntity(ent, true, true, true);
12385         else if (depthonly)
12386         {
12387                 switch (vid.renderpath)
12388                 {
12389                 case RENDERPATH_GL20:
12390                 case RENDERPATH_D3D9:
12391                 case RENDERPATH_D3D10:
12392                 case RENDERPATH_D3D11:
12393                 case RENDERPATH_SOFT:
12394                 case RENDERPATH_GLES2:
12395                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12396                         break;
12397                 case RENDERPATH_GL11:
12398                 case RENDERPATH_GL13:
12399                 case RENDERPATH_GLES1:
12400                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12401                         break;
12402                 }
12403         }
12404         else
12405         {
12406                 switch (vid.renderpath)
12407                 {
12408                 case RENDERPATH_GL20:
12409                 case RENDERPATH_D3D9:
12410                 case RENDERPATH_D3D10:
12411                 case RENDERPATH_D3D11:
12412                 case RENDERPATH_SOFT:
12413                 case RENDERPATH_GLES2:
12414                         RSurf_ActiveModelEntity(ent, true, true, false);
12415                         break;
12416                 case RENDERPATH_GL11:
12417                 case RENDERPATH_GL13:
12418                 case RENDERPATH_GLES1:
12419                         RSurf_ActiveModelEntity(ent, true, false, false);
12420                         break;
12421                 }
12422         }
12423
12424         surfaces = model->data_surfaces;
12425         update = model->brushq1.lightmapupdateflags;
12426
12427         // update light styles
12428         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12429         {
12430                 model_brush_lightstyleinfo_t *style;
12431                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12432                 {
12433                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12434                         {
12435                                 int *list = style->surfacelist;
12436                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12437                                 for (j = 0;j < style->numsurfaces;j++)
12438                                         update[list[j]] = true;
12439                         }
12440                 }
12441         }
12442
12443         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12444
12445         if (debug)
12446         {
12447                 R_DrawDebugModel();
12448                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12449                 return;
12450         }
12451
12452         rsurface.lightmaptexture = NULL;
12453         rsurface.deluxemaptexture = NULL;
12454         rsurface.uselightmaptexture = false;
12455         rsurface.texture = NULL;
12456         rsurface.rtlight = NULL;
12457         numsurfacelist = 0;
12458         // add visible surfaces to draw list
12459         if (ent == r_refdef.scene.worldentity)
12460         {
12461                 // for the world entity, check surfacevisible
12462                 for (i = 0;i < model->nummodelsurfaces;i++)
12463                 {
12464                         j = model->sortedmodelsurfaces[i];
12465                         if (r_refdef.viewcache.world_surfacevisible[j])
12466                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12467                 }
12468         }
12469         else
12470         {
12471                 // add all surfaces
12472                 for (i = 0; i < model->nummodelsurfaces; i++)
12473                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12474         }
12475         // don't do anything if there were no surfaces
12476         if (!numsurfacelist)
12477         {
12478                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12479                 return;
12480         }
12481         // update lightmaps if needed
12482         if (update)
12483         {
12484                 int updated = 0;
12485                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12486                 {
12487                         if (update[j])
12488                         {
12489                                 updated++;
12490                                 R_BuildLightMap(ent, surfaces + j);
12491                         }
12492                 }
12493         }
12494
12495         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12496
12497         // add to stats if desired
12498         if (r_speeds.integer && !skysurfaces && !depthonly)
12499         {
12500                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12501                 for (j = 0;j < numsurfacelist;j++)
12502                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12503         }
12504
12505         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12506 }
12507
12508 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12509 {
12510         int q;
12511         static texture_t texture;
12512         static msurface_t surface;
12513         const msurface_t *surfacelist = &surface;
12514
12515         // fake enough texture and surface state to render this geometry
12516
12517         texture.update_lastrenderframe = -1; // regenerate this texture
12518         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12519         texture.basealpha = 1.0f;
12520         texture.currentskinframe = skinframe;
12521         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12522         texture.offsetmapping = OFFSETMAPPING_OFF;
12523         texture.offsetscale = 1;
12524         texture.specularscalemod = 1;
12525         texture.specularpowermod = 1;
12526         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12527         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12528         // JUST GREP FOR "specularscalemod = 1".
12529
12530         for (q = 0; q < 3; q++)
12531         {
12532                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12533                 texture.render_modellight_lightdir[q] = q == 2;
12534                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12535                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12536                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12537                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12538                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12539                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12540                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12541                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12542         }
12543         texture.currentalpha = 1.0f;
12544
12545         surface.texture = &texture;
12546         surface.num_triangles = numtriangles;
12547         surface.num_firsttriangle = firsttriangle;
12548         surface.num_vertices = numvertices;
12549         surface.num_firstvertex = firstvertex;
12550
12551         // now render it
12552         rsurface.texture = R_GetCurrentTexture(surface.texture);
12553         rsurface.lightmaptexture = NULL;
12554         rsurface.deluxemaptexture = NULL;
12555         rsurface.uselightmaptexture = false;
12556         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12557 }
12558
12559 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)
12560 {
12561         static msurface_t surface;
12562         const msurface_t *surfacelist = &surface;
12563
12564         // fake enough texture and surface state to render this geometry
12565         surface.texture = texture;
12566         surface.num_triangles = numtriangles;
12567         surface.num_firsttriangle = firsttriangle;
12568         surface.num_vertices = numvertices;
12569         surface.num_firstvertex = firstvertex;
12570
12571         // now render it
12572         rsurface.texture = R_GetCurrentTexture(surface.texture);
12573         rsurface.lightmaptexture = NULL;
12574         rsurface.deluxemaptexture = NULL;
12575         rsurface.uselightmaptexture = false;
12576         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12577 }