]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added Draw_GetPicWidth, Draw_GetPicHeight, Draw_IsPicLoaded functions and moved cache...
[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 extern qboolean r_shadow_usingdeferredprepass;
2147 extern rtexture_t *r_shadow_attenuationgradienttexture;
2148 extern rtexture_t *r_shadow_attenuation2dtexture;
2149 extern rtexture_t *r_shadow_attenuation3dtexture;
2150 extern qboolean r_shadow_usingshadowmap2d;
2151 extern qboolean r_shadow_usingshadowmaportho;
2152 extern float r_shadow_modelshadowmap_texturescale[4];
2153 extern float r_shadow_modelshadowmap_parameters[4];
2154 extern float r_shadow_lightshadowmap_texturescale[4];
2155 extern float r_shadow_lightshadowmap_parameters[4];
2156 extern qboolean r_shadow_shadowmapvsdct;
2157 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2159 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2160 extern matrix4x4_t r_shadow_shadowmapmatrix;
2161 extern int r_shadow_prepass_width;
2162 extern int r_shadow_prepass_height;
2163 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2164 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2165 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2166 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2167
2168 #define BLENDFUNC_ALLOWS_COLORMOD      1
2169 #define BLENDFUNC_ALLOWS_FOG           2
2170 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2171 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2172 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2173 static int R_BlendFuncFlags(int src, int dst)
2174 {
2175         int r = 0;
2176
2177         // a blendfunc allows colormod if:
2178         // a) it can never keep the destination pixel invariant, or
2179         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2180         // this is to prevent unintended side effects from colormod
2181
2182         // a blendfunc allows fog if:
2183         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2184         // this is to prevent unintended side effects from fog
2185
2186         // these checks are the output of fogeval.pl
2187
2188         r |= BLENDFUNC_ALLOWS_COLORMOD;
2189         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2198         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2199         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2201         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2202         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2205         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2207         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2208         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2209         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2210
2211         return r;
2212 }
2213
2214 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2215 {
2216         // select a permutation of the lighting shader appropriate to this
2217         // combination of texture, entity, light source, and fogging, only use the
2218         // minimum features necessary to avoid wasting rendering time in the
2219         // fragment shader on features that are not being used
2220         dpuint64 permutation = 0;
2221         unsigned int mode = 0;
2222         int blendfuncflags;
2223         texture_t *t = rsurface.texture;
2224         float m16f[16];
2225         matrix4x4_t tempmatrix;
2226         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2227         if (r_trippy.integer && !notrippy)
2228                 permutation |= SHADERPERMUTATION_TRIPPY;
2229         if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2230                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2231         if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2232                 permutation |= SHADERPERMUTATION_OCCLUDE;
2233         if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2234                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2235         if (rsurfacepass == RSURFPASS_BACKGROUND)
2236         {
2237                 // distorted background
2238                 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2239                 {
2240                         mode = SHADERMODE_WATER;
2241                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2242                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2243                         if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2244                         {
2245                                 // this is the right thing to do for wateralpha
2246                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2247                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2248                         }
2249                         else
2250                         {
2251                                 // this is the right thing to do for entity alpha
2252                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254                         }
2255                 }
2256                 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2257                 {
2258                         mode = SHADERMODE_REFRACTION;
2259                         if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2260                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2261                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263                 }
2264                 else
2265                 {
2266                         mode = SHADERMODE_GENERIC;
2267                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2268                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2269                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2270                 }
2271                 if (vid.allowalphatocoverage)
2272                         GL_AlphaToCoverage(false);
2273         }
2274         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2275         {
2276                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2277                 {
2278                         switch(t->offsetmapping)
2279                         {
2280                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283                         case OFFSETMAPPING_OFF: break;
2284                         }
2285                 }
2286                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288                 // normalmap (deferred prepass), may use alpha test on diffuse
2289                 mode = SHADERMODE_DEFERREDGEOMETRY;
2290                 GL_BlendFunc(GL_ONE, GL_ZERO);
2291                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2292                 if (vid.allowalphatocoverage)
2293                         GL_AlphaToCoverage(false);
2294         }
2295         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2296         {
2297                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2298                 {
2299                         switch(t->offsetmapping)
2300                         {
2301                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304                         case OFFSETMAPPING_OFF: break;
2305                         }
2306                 }
2307                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2310                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2311                 // light source
2312                 mode = SHADERMODE_LIGHTSOURCE;
2313                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2314                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2315                 if (VectorLength2(rtlightdiffuse) > 0)
2316                         permutation |= SHADERPERMUTATION_DIFFUSE;
2317                 if (VectorLength2(rtlightspecular) > 0)
2318                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2319                 if (r_refdef.fogenabled)
2320                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321                 if (t->colormapping)
2322                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2323                 if (r_shadow_usingshadowmap2d)
2324                 {
2325                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2326                         if(r_shadow_shadowmapvsdct)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2328
2329                         if (r_shadow_shadowmap2ddepthbuffer)
2330                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2331                 }
2332                 if (t->reflectmasktexture)
2333                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2335                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2336                 if (vid.allowalphatocoverage)
2337                         GL_AlphaToCoverage(false);
2338         }
2339         else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2340         {
2341                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2342                 {
2343                         switch(t->offsetmapping)
2344                         {
2345                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2346                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_OFF: break;
2349                         }
2350                 }
2351                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2352                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2354                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2355                 // directional model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (VectorLength2(t->render_modellight_diffuse))
2360                         permutation |= SHADERPERMUTATION_DIFFUSE;
2361                 if (VectorLength2(t->render_modellight_specular) > 0)
2362                         permutation |= SHADERPERMUTATION_SPECULAR;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (t->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmap2ddepthbuffer)
2373                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374                 }
2375                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (t->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegrid_state.directional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2404                 {
2405                         switch(t->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2417                 // lightmapped wall
2418                 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419                         permutation |= SHADERPERMUTATION_GLOW;
2420                 if (r_refdef.fogenabled)
2421                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422                 if (t->colormapping)
2423                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2424                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425                 {
2426                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428
2429                         if (r_shadow_shadowmap2ddepthbuffer)
2430                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2431                 }
2432                 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433                         permutation |= SHADERPERMUTATION_REFLECTION;
2434                 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2435                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436                 if (t->reflectmasktexture)
2437                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438                 if (FAKELIGHT_ENABLED)
2439                 {
2440                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441                         mode = SHADERMODE_FAKELIGHT;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (VectorLength2(t->render_lightmap_specular) > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447                 {
2448                         // deluxemapping (light direction texture)
2449                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451                         else
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (VectorLength2(t->render_lightmap_specular) > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 2)
2458                 {
2459                         // fake deluxemapping (uniform light direction in tangentspace)
2460                         if (rsurface.uselightmaptexture)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (VectorLength2(t->render_lightmap_specular) > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (rsurface.uselightmaptexture)
2469                 {
2470                         // ordinary lightmapping (q1bsp, q3bsp)
2471                         mode = SHADERMODE_LIGHTMAP;
2472                 }
2473                 else
2474                 {
2475                         // ordinary vertex coloring (q3bsp)
2476                         mode = SHADERMODE_VERTEXCOLOR;
2477                 }
2478                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2479                 {
2480                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481                         if (r_shadow_bouncegrid_state.directional)
2482                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483                 }
2484                 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2485                 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486                 // when using alphatocoverage, we don't need alphakill
2487                 if (vid.allowalphatocoverage)
2488                 {
2489                         if (r_transparent_alphatocoverage.integer)
2490                         {
2491                                 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493                         }
2494                         else
2495                                 GL_AlphaToCoverage(false);
2496                 }
2497         }
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502         switch(vid.renderpath)
2503         {
2504         case RENDERPATH_D3D9:
2505 #ifdef SUPPORTD3D
2506                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2507                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2508                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510                 if (mode == SHADERMODE_LIGHTSOURCE)
2511                 {
2512                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2514                 }
2515                 else
2516                 {
2517                         if (mode == SHADERMODE_LIGHTDIRECTION)
2518                         {
2519                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2520                         }
2521                 }
2522                 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523                 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2532                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2535
2536                         // additive passes are only darkened by fog, not tinted
2537                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2539                 }
2540                 else
2541                 {
2542                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2544                         if (mode == SHADERMODE_FLATCOLOR)
2545                         {
2546                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2547                         }
2548                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2555                         }
2556                         else
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2561                         }
2562                         // additive passes are only darkened by fog, not tinted
2563                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2565                         else
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2567                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2568                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2572                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2573                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2575                         if (mode == SHADERMODE_WATER)
2576                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2577                 }
2578                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2579                 {
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2582                 }
2583                 else
2584                 {
2585                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2586                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2587                 }
2588                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2589                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2590                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2591                 if (t->pantstexture)
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2593                 else
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2595                 if (t->shirttexture)
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2597                 else
2598                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2602                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2603                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2604                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2605                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2608                         );
2609                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2610                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2611                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2612                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2613
2614                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2615                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2616                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2617                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2622                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2624                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2626                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2627                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2628                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2629                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2630                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2631                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2632                 {
2633                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2634                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2635                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636                 }
2637                 else
2638                 {
2639                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2640                 }
2641 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2642                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2643                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2644                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2645                 {
2646                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2647                         if (rsurface.rtlight)
2648                         {
2649                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2650                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2651                         }
2652                 }
2653 #endif
2654                 break;
2655         case RENDERPATH_D3D10:
2656                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657                 break;
2658         case RENDERPATH_D3D11:
2659                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2660                 break;
2661         case RENDERPATH_GL20:
2662         case RENDERPATH_GLES2:
2663                 if (!vid.useinterleavedarrays)
2664                 {
2665                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2666                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2667                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2674                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2675                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2676                 }
2677                 else
2678                 {
2679                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2680                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2681                 }
2682                 // this has to be after RSurf_PrepareVerticesForBatch
2683                 if (rsurface.batchskeletaltransform3x4buffer)
2684                         permutation |= SHADERPERMUTATION_SKELETAL;
2685                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2687                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2688 #endif
2689                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2690                 if (mode == SHADERMODE_LIGHTSOURCE)
2691                 {
2692                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2693                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2694                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2695                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2696                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2697                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2698         
2699                         // additive passes are only darkened by fog, not tinted
2700                         if (r_glsl_permutation->loc_FogColor >= 0)
2701                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2702                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2703                 }
2704                 else
2705                 {
2706                         if (mode == SHADERMODE_FLATCOLOR)
2707                         {
2708                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2709                         }
2710                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2711                         {
2712                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2713                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2714                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2715                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2716                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2717                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2718                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2719                         }
2720                         else
2721                         {
2722                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2723                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2724                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2725                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2726                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2727                         }
2728                         // additive passes are only darkened by fog, not tinted
2729                         if (r_glsl_permutation->loc_FogColor >= 0)
2730                         {
2731                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2732                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2733                                 else
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2735                         }
2736                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2737                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2738                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2739                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2740                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2741                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2742                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2743                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2744                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2745                 }
2746                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2747                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2749                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2750                 {
2751                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2752                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2753                 }
2754                 else
2755                 {
2756                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2757                         if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2758                 }
2759
2760                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2761                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2762                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2763                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2764                 {
2765                         if (t->pantstexture)
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2767                         else
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2769                 }
2770                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2771                 {
2772                         if (t->shirttexture)
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2774                         else
2775                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2776                 }
2777                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2778                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2779                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2780                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2781                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2782                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2783                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2784                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2786                         );
2787                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2788                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2789                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2790                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2791                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2792                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2793
2794                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2795                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2796                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2797                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , t->nmaptexture                       );
2798                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , t->basetexture                       );
2799                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , t->glosstexture                      );
2800                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , t->glowtexture                       );
2801                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , t->backgroundnmaptexture             );
2802                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , t->backgroundbasetexture             );
2803                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , t->backgroundglosstexture            );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , t->backgroundglowtexture             );
2805                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , t->pantstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , t->shirttexture                      );
2807                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , t->reflectmasktexture                );
2808                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2809                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2810                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2811                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2814                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2815                 {
2816                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2817                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2818                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2819                 }
2820                 else
2821                 {
2822                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2823                 }
2824                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2825                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2826                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2827                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2828                 {
2829                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2830                         if (rsurface.rtlight)
2831                         {
2832                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2833                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2834                         }
2835                 }
2836                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2837                 CHECKGLERROR
2838                 break;
2839         case RENDERPATH_GL11:
2840         case RENDERPATH_GL13:
2841         case RENDERPATH_GLES1:
2842                 break;
2843         case RENDERPATH_SOFT:
2844                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2845                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2846                 R_SetupShader_SetPermutationSoft(mode, permutation);
2847                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2848                 if (mode == SHADERMODE_LIGHTSOURCE)
2849                 {
2850                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2856         
2857                         // additive passes are only darkened by fog, not tinted
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2859                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2860                 }
2861                 else
2862                 {
2863                         if (mode == SHADERMODE_FLATCOLOR)
2864                         {
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2866                         }
2867                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2874                         }
2875                         else
2876                         {
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2880                         }
2881                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2882                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2883                         // additive passes are only darkened by fog, not tinted
2884                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2886                         else
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2888                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2889                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2890                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2891                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2892                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2893                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2897                 }
2898                 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2899                 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2900                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2901                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2902                 {
2903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2905                 }
2906                 else
2907                 {
2908                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2909                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2910                 }
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2913                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (t->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (t->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934                                 r_glsl_offsetmapping_scale.value*t->offsetscale,
2935                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938                         );
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_NORMAL            , t->nmaptexture                       );
2945                 R_Mesh_TexBind(GL20TU_COLOR             , t->basetexture                       );
2946                 R_Mesh_TexBind(GL20TU_GLOSS             , t->glosstexture                      );
2947                 R_Mesh_TexBind(GL20TU_GLOW              , t->glowtexture                       );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , t->backgroundnmaptexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , t->backgroundbasetexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , t->backgroundglosstexture            );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , t->backgroundglowtexture             );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , t->pantstexture                      );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , t->shirttexture                      );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , t->reflectmasktexture                );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2956                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2962                 {
2963                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967                 else
2968                 {
2969                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975                 {
2976                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977                         if (rsurface.rtlight)
2978                         {
2979                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981                         }
2982                 }
2983                 break;
2984         }
2985 }
2986
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989         // select a permutation of the lighting shader appropriate to this
2990         // combination of texture, entity, light source, and fogging, only use the
2991         // minimum features necessary to avoid wasting rendering time in the
2992         // fragment shader on features that are not being used
2993         dpuint64 permutation = 0;
2994         unsigned int mode = 0;
2995         const float *lightcolorbase = rtlight->currentcolor;
2996         float ambientscale = rtlight->ambientscale;
2997         float diffusescale = rtlight->diffusescale;
2998         float specularscale = rtlight->specularscale;
2999         // this is the location of the light in view space
3000         vec3_t viewlightorigin;
3001         // this transforms from view space (camera) to light space (cubemap)
3002         matrix4x4_t viewtolight;
3003         matrix4x4_t lighttoview;
3004         float viewtolight16f[16];
3005         // light source
3006         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007         if (rtlight->currentcubemap != r_texture_whitecube)
3008                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009         if (diffusescale > 0)
3010                 permutation |= SHADERPERMUTATION_DIFFUSE;
3011         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013         if (r_shadow_usingshadowmap2d)
3014         {
3015                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016                 if (r_shadow_shadowmapvsdct)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018
3019                 if (r_shadow_shadowmap2ddepthbuffer)
3020                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3021         }
3022         if (vid.allowalphatocoverage)
3023                 GL_AlphaToCoverage(false);
3024         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3027         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028         switch(vid.renderpath)
3029         {
3030         case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3040                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043
3044                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3066                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3067                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3068                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         case RENDERPATH_GL11:
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GLES1:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3089                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3090                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         }
3101 }
3102
3103 #define SKINFRAME_HASH 1024
3104
3105 typedef struct
3106 {
3107         unsigned int loadsequence; // incremented each level change
3108         memexpandablearray_t array;
3109         skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113
3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116         r_skinframe.loadsequence++;
3117         // wrap it without hitting zero
3118         if (r_skinframe.loadsequence >= 200)
3119                 r_skinframe.loadsequence = 1;
3120 }
3121
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124         if (!skinframe)
3125                 return;
3126         // mark the skinframe as used for the purging code
3127         skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129
3130 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3131 {
3132         if (s->merged == s->base)
3133                 s->merged = NULL;
3134         R_PurgeTexture(s->stain); s->stain = NULL;
3135         R_PurgeTexture(s->merged); s->merged = NULL;
3136         R_PurgeTexture(s->base); s->base = NULL;
3137         R_PurgeTexture(s->pants); s->pants = NULL;
3138         R_PurgeTexture(s->shirt); s->shirt = NULL;
3139         R_PurgeTexture(s->nmap); s->nmap = NULL;
3140         R_PurgeTexture(s->gloss); s->gloss = NULL;
3141         R_PurgeTexture(s->glow); s->glow = NULL;
3142         R_PurgeTexture(s->fog); s->fog = NULL;
3143         R_PurgeTexture(s->reflect); s->reflect = NULL;
3144         s->loadsequence = 0;
3145 }
3146
3147 void R_SkinFrame_Purge(void)
3148 {
3149         int i;
3150         skinframe_t *s;
3151         for (i = 0;i < SKINFRAME_HASH;i++)
3152         {
3153                 for (s = r_skinframe.hash[i];s;s = s->next)
3154                 {
3155                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3156                                 R_SkinFrame_PurgeSkinFrame(s);
3157                 }
3158         }
3159 }
3160
3161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3162         skinframe_t *item;
3163         char basename[MAX_QPATH];
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         if( last == NULL ) {
3168                 int hashindex;
3169                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170                 item = r_skinframe.hash[hashindex];
3171         } else {
3172                 item = last->next;
3173         }
3174
3175         // linearly search through the hash bucket
3176         for( ; item ; item = item->next ) {
3177                 if( !strcmp( item->basename, basename ) ) {
3178                         return item;
3179                 }
3180         }
3181         return NULL;
3182 }
3183
3184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3185 {
3186         skinframe_t *item;
3187         int hashindex;
3188         char basename[MAX_QPATH];
3189
3190         Image_StripImageExtension(name, basename, sizeof(basename));
3191
3192         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3193         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3194                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3195                         break;
3196
3197         if (!item)
3198         {
3199                 if (!add)
3200                         return NULL;
3201                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202                 memset(item, 0, sizeof(*item));
3203                 strlcpy(item->basename, basename, sizeof(item->basename));
3204                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if (textureflags & TEXF_FORCE_RELOAD)
3212         {
3213                 if (!add)
3214                         return NULL;
3215                 R_SkinFrame_PurgeSkinFrame(item);
3216         }
3217
3218         R_SkinFrame_MarkUsed(item);
3219         return item;
3220 }
3221
3222 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3223         { \
3224                 unsigned long long avgcolor[5], wsum; \
3225                 int pix, comp, w; \
3226                 avgcolor[0] = 0; \
3227                 avgcolor[1] = 0; \
3228                 avgcolor[2] = 0; \
3229                 avgcolor[3] = 0; \
3230                 avgcolor[4] = 0; \
3231                 wsum = 0; \
3232                 for(pix = 0; pix < cnt; ++pix) \
3233                 { \
3234                         w = 0; \
3235                         for(comp = 0; comp < 3; ++comp) \
3236                                 w += getpixel; \
3237                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3238                         { \
3239                                 ++wsum; \
3240                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3241                                 w = getpixel; \
3242                                 for(comp = 0; comp < 3; ++comp) \
3243                                         avgcolor[comp] += getpixel * w; \
3244                                 avgcolor[3] += w; \
3245                         } \
3246                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247                         avgcolor[4] += getpixel; \
3248                 } \
3249                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3250                         avgcolor[3] = 1; \
3251                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3252                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3253                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3254                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3255         }
3256
3257 extern cvar_t gl_picmip;
3258 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3259 {
3260         int j;
3261         unsigned char *pixels;
3262         unsigned char *bumppixels;
3263         unsigned char *basepixels = NULL;
3264         int basepixels_width = 0;
3265         int basepixels_height = 0;
3266         skinframe_t *skinframe;
3267         rtexture_t *ddsbase = NULL;
3268         qboolean ddshasalpha = false;
3269         float ddsavgcolor[4];
3270         char basename[MAX_QPATH];
3271         int miplevel = R_PicmipForFlags(textureflags);
3272         int savemiplevel = miplevel;
3273         int mymiplevel;
3274         char vabuf[1024];
3275
3276         if (cls.state == ca_dedicated)
3277                 return NULL;
3278
3279         // return an existing skinframe if already loaded
3280         // if loading of the first image fails, don't make a new skinframe as it
3281         // would cause all future lookups of this to be missing
3282         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3283         if (skinframe && skinframe->base)
3284                 return skinframe;
3285
3286         Image_StripImageExtension(name, basename, sizeof(basename));
3287
3288         // check for DDS texture file first
3289         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3290         {
3291                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3292                 if (basepixels == NULL && fallbacknotexture)
3293                         basepixels = Image_GenerateNoTexture();
3294                 if (basepixels == NULL)
3295                         return NULL;
3296         }
3297
3298         // FIXME handle miplevel
3299
3300         if (developer_loading.integer)
3301                 Con_Printf("loading skin \"%s\"\n", name);
3302
3303         // we've got some pixels to store, so really allocate this new texture now
3304         if (!skinframe)
3305                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3306         textureflags &= ~TEXF_FORCE_RELOAD;
3307         skinframe->stain = NULL;
3308         skinframe->merged = NULL;
3309         skinframe->base = NULL;
3310         skinframe->pants = NULL;
3311         skinframe->shirt = NULL;
3312         skinframe->nmap = NULL;
3313         skinframe->gloss = NULL;
3314         skinframe->glow = NULL;
3315         skinframe->fog = NULL;
3316         skinframe->reflect = NULL;
3317         skinframe->hasalpha = false;
3318         // we could store the q2animname here too
3319
3320         if (ddsbase)
3321         {
3322                 skinframe->base = ddsbase;
3323                 skinframe->hasalpha = ddshasalpha;
3324                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3325                 if (r_loadfog && skinframe->hasalpha)
3326                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3327                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3328         }
3329         else
3330         {
3331                 basepixels_width = image_width;
3332                 basepixels_height = image_height;
3333                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3334                 if (textureflags & TEXF_ALPHA)
3335                 {
3336                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3337                         {
3338                                 if (basepixels[j] < 255)
3339                                 {
3340                                         skinframe->hasalpha = true;
3341                                         break;
3342                                 }
3343                         }
3344                         if (r_loadfog && skinframe->hasalpha)
3345                         {
3346                                 // has transparent pixels
3347                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3348                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3349                                 {
3350                                         pixels[j+0] = 255;
3351                                         pixels[j+1] = 255;
3352                                         pixels[j+2] = 255;
3353                                         pixels[j+3] = basepixels[j+3];
3354                                 }
3355                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3356                                 Mem_Free(pixels);
3357                         }
3358                 }
3359                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3360 #ifndef USE_GLES2
3361                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3362                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3363                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3364                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3365                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3366 #endif
3367         }
3368
3369         if (r_loaddds)
3370         {
3371                 mymiplevel = savemiplevel;
3372                 if (r_loadnormalmap)
3373                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3374                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3375                 if (r_loadgloss)
3376                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3377                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3379                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3380         }
3381
3382         // _norm is the name used by tenebrae and has been adopted as standard
3383         if (r_loadnormalmap && skinframe->nmap == NULL)
3384         {
3385                 mymiplevel = savemiplevel;
3386                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3387                 {
3388                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3389                         Mem_Free(pixels);
3390                         pixels = NULL;
3391                 }
3392                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3393                 {
3394                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3395                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3396                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3397                         Mem_Free(pixels);
3398                         Mem_Free(bumppixels);
3399                 }
3400                 else if (r_shadow_bumpscale_basetexture.value > 0)
3401                 {
3402                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3403                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3404                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3405                         Mem_Free(pixels);
3406                 }
3407 #ifndef USE_GLES2
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3409                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410 #endif
3411         }
3412
3413         // _luma is supported only for tenebrae compatibility
3414         // _glow is the preferred name
3415         mymiplevel = savemiplevel;
3416         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3417         {
3418                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3419 #ifndef USE_GLES2
3420                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3421                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3422 #endif
3423                 Mem_Free(pixels);pixels = NULL;
3424         }
3425
3426         mymiplevel = savemiplevel;
3427         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3428         {
3429                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3430 #ifndef USE_GLES2
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3432                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434                 Mem_Free(pixels);
3435                 pixels = NULL;
3436         }
3437
3438         mymiplevel = savemiplevel;
3439         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3440         {
3441                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3444                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3445 #endif
3446                 Mem_Free(pixels);
3447                 pixels = NULL;
3448         }
3449
3450         mymiplevel = savemiplevel;
3451         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3452         {
3453                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3456                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3457 #endif
3458                 Mem_Free(pixels);
3459                 pixels = NULL;
3460         }
3461
3462         mymiplevel = savemiplevel;
3463         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3464         {
3465                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3466 #ifndef USE_GLES2
3467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3468                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3469 #endif
3470                 Mem_Free(pixels);
3471                 pixels = NULL;
3472         }
3473
3474         if (basepixels)
3475                 Mem_Free(basepixels);
3476
3477         return skinframe;
3478 }
3479
3480 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3481 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3482 {
3483         int i;
3484         skinframe_t *skinframe;
3485         char vabuf[1024];
3486
3487         if (cls.state == ca_dedicated)
3488                 return NULL;
3489
3490         // if already loaded just return it, otherwise make a new skinframe
3491         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3492         if (skinframe->base)
3493                 return skinframe;
3494         textureflags &= ~TEXF_FORCE_RELOAD;
3495
3496         skinframe->stain = NULL;
3497         skinframe->merged = NULL;
3498         skinframe->base = NULL;
3499         skinframe->pants = NULL;
3500         skinframe->shirt = NULL;
3501         skinframe->nmap = NULL;
3502         skinframe->gloss = NULL;
3503         skinframe->glow = NULL;
3504         skinframe->fog = NULL;
3505         skinframe->reflect = NULL;
3506         skinframe->hasalpha = false;
3507
3508         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3509         if (!skindata)
3510                 return NULL;
3511
3512         if (developer_loading.integer)
3513                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3514
3515         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3516         {
3517                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518                 unsigned char *b = a + width * height * 4;
3519                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3520                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3521                 Mem_Free(a);
3522         }
3523         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3524         if (textureflags & TEXF_ALPHA)
3525         {
3526                 for (i = 3;i < width * height * 4;i += 4)
3527                 {
3528                         if (skindata[i] < 255)
3529                         {
3530                                 skinframe->hasalpha = true;
3531                                 break;
3532                         }
3533                 }
3534                 if (r_loadfog && skinframe->hasalpha)
3535                 {
3536                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3537                         memcpy(fogpixels, skindata, width * height * 4);
3538                         for (i = 0;i < width * height * 4;i += 4)
3539                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3540                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3541                         Mem_Free(fogpixels);
3542                 }
3543         }
3544
3545         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3546         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3547
3548         return skinframe;
3549 }
3550
3551 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3552 {
3553         int i;
3554         int featuresmask;
3555         skinframe_t *skinframe;
3556
3557         if (cls.state == ca_dedicated)
3558                 return NULL;
3559
3560         // if already loaded just return it, otherwise make a new skinframe
3561         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562         if (skinframe->base)
3563                 return skinframe;
3564         //textureflags &= ~TEXF_FORCE_RELOAD;
3565
3566         skinframe->stain = NULL;
3567         skinframe->merged = NULL;
3568         skinframe->base = NULL;
3569         skinframe->pants = NULL;
3570         skinframe->shirt = NULL;
3571         skinframe->nmap = NULL;
3572         skinframe->gloss = NULL;
3573         skinframe->glow = NULL;
3574         skinframe->fog = NULL;
3575         skinframe->reflect = NULL;
3576         skinframe->hasalpha = false;
3577
3578         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3579         if (!skindata)
3580                 return NULL;
3581
3582         if (developer_loading.integer)
3583                 Con_Printf("loading quake skin \"%s\"\n", name);
3584
3585         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3586         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3587         memcpy(skinframe->qpixels, skindata, width*height);
3588         skinframe->qwidth = width;
3589         skinframe->qheight = height;
3590
3591         featuresmask = 0;
3592         for (i = 0;i < width * height;i++)
3593                 featuresmask |= palette_featureflags[skindata[i]];
3594
3595         skinframe->hasalpha = false;
3596         // fence textures
3597         if (name[0] == '{')
3598                 skinframe->hasalpha = true;
3599         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3600         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3601         skinframe->qgeneratemerged = true;
3602         skinframe->qgeneratebase = skinframe->qhascolormapping;
3603         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3604
3605         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3606         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3607
3608         return skinframe;
3609 }
3610
3611 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3612 {
3613         int width;
3614         int height;
3615         unsigned char *skindata;
3616         char vabuf[1024];
3617
3618         if (!skinframe->qpixels)
3619                 return;
3620
3621         if (!skinframe->qhascolormapping)
3622                 colormapped = false;
3623
3624         if (colormapped)
3625         {
3626                 if (!skinframe->qgeneratebase)
3627                         return;
3628         }
3629         else
3630         {
3631                 if (!skinframe->qgeneratemerged)
3632                         return;
3633         }
3634
3635         width = skinframe->qwidth;
3636         height = skinframe->qheight;
3637         skindata = skinframe->qpixels;
3638
3639         if (skinframe->qgeneratenmap)
3640         {
3641                 unsigned char *a, *b;
3642                 skinframe->qgeneratenmap = false;
3643                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3644                 b = a + width * height * 4;
3645                 // use either a custom palette or the quake palette
3646                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3647                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3648                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3649                 Mem_Free(a);
3650         }
3651
3652         if (skinframe->qgenerateglow)
3653         {
3654                 skinframe->qgenerateglow = false;
3655                 if (skinframe->hasalpha) // fence textures
3656                         skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3657                 else
3658                         skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3659         }
3660
3661         if (colormapped)
3662         {
3663                 skinframe->qgeneratebase = false;
3664                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3665                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3666                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3667         }
3668         else
3669         {
3670                 skinframe->qgeneratemerged = false;
3671                 if (skinframe->hasalpha) // fence textures
3672                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3673                 else
3674                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3675         }
3676
3677         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3678         {
3679                 Mem_Free(skinframe->qpixels);
3680                 skinframe->qpixels = NULL;
3681         }
3682 }
3683
3684 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3685 {
3686         int i;
3687         skinframe_t *skinframe;
3688         char vabuf[1024];
3689
3690         if (cls.state == ca_dedicated)
3691                 return NULL;
3692
3693         // if already loaded just return it, otherwise make a new skinframe
3694         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3695         if (skinframe->base)
3696                 return skinframe;
3697         textureflags &= ~TEXF_FORCE_RELOAD;
3698
3699         skinframe->stain = NULL;
3700         skinframe->merged = NULL;
3701         skinframe->base = NULL;
3702         skinframe->pants = NULL;
3703         skinframe->shirt = NULL;
3704         skinframe->nmap = NULL;
3705         skinframe->gloss = NULL;
3706         skinframe->glow = NULL;
3707         skinframe->fog = NULL;
3708         skinframe->reflect = NULL;
3709         skinframe->hasalpha = false;
3710
3711         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3712         if (!skindata)
3713                 return NULL;
3714
3715         if (developer_loading.integer)
3716                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3717
3718         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3719         if ((textureflags & TEXF_ALPHA) && alphapalette)
3720         {
3721                 for (i = 0;i < width * height;i++)
3722                 {
3723                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3724                         {
3725                                 skinframe->hasalpha = true;
3726                                 break;
3727                         }
3728                 }
3729                 if (r_loadfog && skinframe->hasalpha)
3730                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3731         }
3732
3733         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3734         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3735
3736         return skinframe;
3737 }
3738
3739 skinframe_t *R_SkinFrame_LoadMissing(void)
3740 {
3741         skinframe_t *skinframe;
3742
3743         if (cls.state == ca_dedicated)
3744                 return NULL;
3745
3746         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3747         skinframe->stain = NULL;
3748         skinframe->merged = NULL;
3749         skinframe->base = NULL;
3750         skinframe->pants = NULL;
3751         skinframe->shirt = NULL;
3752         skinframe->nmap = NULL;
3753         skinframe->gloss = NULL;
3754         skinframe->glow = NULL;
3755         skinframe->fog = NULL;
3756         skinframe->reflect = NULL;
3757         skinframe->hasalpha = false;
3758
3759         skinframe->avgcolor[0] = rand() / RAND_MAX;
3760         skinframe->avgcolor[1] = rand() / RAND_MAX;
3761         skinframe->avgcolor[2] = rand() / RAND_MAX;
3762         skinframe->avgcolor[3] = 1;
3763
3764         return skinframe;
3765 }
3766
3767 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3768 {
3769         int x, y;
3770         static unsigned char pix[16][16][4];
3771
3772         if (cls.state == ca_dedicated)
3773                 return NULL;
3774
3775         // this makes a light grey/dark grey checkerboard texture
3776         if (!pix[0][0][3])
3777         {
3778                 for (y = 0; y < 16; y++)
3779                 {
3780                         for (x = 0; x < 16; x++)
3781                         {
3782                                 if ((y < 8) ^ (x < 8))
3783                                 {
3784                                         pix[y][x][0] = 128;
3785                                         pix[y][x][1] = 128;
3786                                         pix[y][x][2] = 128;
3787                                         pix[y][x][3] = 255;
3788                                 }
3789                                 else
3790                                 {
3791                                         pix[y][x][0] = 64;
3792                                         pix[y][x][1] = 64;
3793                                         pix[y][x][2] = 64;
3794                                         pix[y][x][3] = 255;
3795                                 }
3796                         }
3797                 }
3798         }
3799
3800         return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3801 }
3802
3803 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3804 {
3805         skinframe_t *skinframe;
3806         if (cls.state == ca_dedicated)
3807                 return NULL;
3808         // if already loaded just return it, otherwise make a new skinframe
3809         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3810         if (skinframe->base)
3811                 return skinframe;
3812         textureflags &= ~TEXF_FORCE_RELOAD;
3813         skinframe->stain = NULL;
3814         skinframe->merged = NULL;
3815         skinframe->base = NULL;
3816         skinframe->pants = NULL;
3817         skinframe->shirt = NULL;
3818         skinframe->nmap = NULL;
3819         skinframe->gloss = NULL;
3820         skinframe->glow = NULL;
3821         skinframe->fog = NULL;
3822         skinframe->reflect = NULL;
3823         skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3824         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3825         if (!tex)
3826                 return NULL;
3827         if (developer_loading.integer)
3828                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3829         skinframe->base = skinframe->merged = tex;
3830         Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3831         return skinframe;
3832 }
3833
3834 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3835 typedef struct suffixinfo_s
3836 {
3837         const char *suffix;
3838         qboolean flipx, flipy, flipdiagonal;
3839 }
3840 suffixinfo_t;
3841 static suffixinfo_t suffix[3][6] =
3842 {
3843         {
3844                 {"px",   false, false, false},
3845                 {"nx",   false, false, false},
3846                 {"py",   false, false, false},
3847                 {"ny",   false, false, false},
3848                 {"pz",   false, false, false},
3849                 {"nz",   false, false, false}
3850         },
3851         {
3852                 {"posx", false, false, false},
3853                 {"negx", false, false, false},
3854                 {"posy", false, false, false},
3855                 {"negy", false, false, false},
3856                 {"posz", false, false, false},
3857                 {"negz", false, false, false}
3858         },
3859         {
3860                 {"rt",    true, false,  true},
3861                 {"lf",   false,  true,  true},
3862                 {"ft",    true,  true, false},
3863                 {"bk",   false, false, false},
3864                 {"up",    true, false,  true},
3865                 {"dn",    true, false,  true}
3866         }
3867 };
3868
3869 static int componentorder[4] = {0, 1, 2, 3};
3870
3871 static rtexture_t *R_LoadCubemap(const char *basename)
3872 {
3873         int i, j, cubemapsize;
3874         unsigned char *cubemappixels, *image_buffer;
3875         rtexture_t *cubemaptexture;
3876         char name[256];
3877         // must start 0 so the first loadimagepixels has no requested width/height
3878         cubemapsize = 0;
3879         cubemappixels = NULL;
3880         cubemaptexture = NULL;
3881         // keep trying different suffix groups (posx, px, rt) until one loads
3882         for (j = 0;j < 3 && !cubemappixels;j++)
3883         {
3884                 // load the 6 images in the suffix group
3885                 for (i = 0;i < 6;i++)
3886                 {
3887                         // generate an image name based on the base and and suffix
3888                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3889                         // load it
3890                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3891                         {
3892                                 // an image loaded, make sure width and height are equal
3893                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3894                                 {
3895                                         // if this is the first image to load successfully, allocate the cubemap memory
3896                                         if (!cubemappixels && image_width >= 1)
3897                                         {
3898                                                 cubemapsize = image_width;
3899                                                 // note this clears to black, so unavailable sides are black
3900                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3901                                         }
3902                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3903                                         if (cubemappixels)
3904                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3905                                 }
3906                                 else
3907                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3908                                 // free the image
3909                                 Mem_Free(image_buffer);
3910                         }
3911                 }
3912         }
3913         // if a cubemap loaded, upload it
3914         if (cubemappixels)
3915         {
3916                 if (developer_loading.integer)
3917                         Con_Printf("loading cubemap \"%s\"\n", basename);
3918
3919                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3920                 Mem_Free(cubemappixels);
3921         }
3922         else
3923         {
3924                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3925                 if (developer_loading.integer)
3926                 {
3927                         Con_Printf("(tried tried images ");
3928                         for (j = 0;j < 3;j++)
3929                                 for (i = 0;i < 6;i++)
3930                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3931                         Con_Print(" and was unable to find any of them).\n");
3932                 }
3933         }
3934         return cubemaptexture;
3935 }
3936
3937 rtexture_t *R_GetCubemap(const char *basename)
3938 {
3939         int i;
3940         for (i = 0;i < r_texture_numcubemaps;i++)
3941                 if (r_texture_cubemaps[i] != NULL)
3942                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3943                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3944         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3945                 return r_texture_whitecube;
3946         r_texture_numcubemaps++;
3947         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3948         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3949         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3950         return r_texture_cubemaps[i]->texture;
3951 }
3952
3953 static void R_Main_FreeViewCache(void)
3954 {
3955         if (r_refdef.viewcache.entityvisible)
3956                 Mem_Free(r_refdef.viewcache.entityvisible);
3957         if (r_refdef.viewcache.world_pvsbits)
3958                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3959         if (r_refdef.viewcache.world_leafvisible)
3960                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3961         if (r_refdef.viewcache.world_surfacevisible)
3962                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3964 }
3965
3966 static void R_Main_ResizeViewCache(void)
3967 {
3968         int numentities = r_refdef.scene.numentities;
3969         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3970         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3971         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3972         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3973         if (r_refdef.viewcache.maxentities < numentities)
3974         {
3975                 r_refdef.viewcache.maxentities = numentities;
3976                 if (r_refdef.viewcache.entityvisible)
3977                         Mem_Free(r_refdef.viewcache.entityvisible);
3978                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3979         }
3980         if (r_refdef.viewcache.world_numclusters != numclusters)
3981         {
3982                 r_refdef.viewcache.world_numclusters = numclusters;
3983                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3984                 if (r_refdef.viewcache.world_pvsbits)
3985                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3986                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3987         }
3988         if (r_refdef.viewcache.world_numleafs != numleafs)
3989         {
3990                 r_refdef.viewcache.world_numleafs = numleafs;
3991                 if (r_refdef.viewcache.world_leafvisible)
3992                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3993                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3994         }
3995         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3996         {
3997                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3998                 if (r_refdef.viewcache.world_surfacevisible)
3999                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4000                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4001         }
4002 }
4003
4004 extern rtexture_t *loadingscreentexture;
4005 static void gl_main_start(void)
4006 {
4007         loadingscreentexture = NULL;
4008         r_texture_blanknormalmap = NULL;
4009         r_texture_white = NULL;
4010         r_texture_grey128 = NULL;
4011         r_texture_black = NULL;
4012         r_texture_whitecube = NULL;
4013         r_texture_normalizationcube = NULL;
4014         r_texture_fogattenuation = NULL;
4015         r_texture_fogheighttexture = NULL;
4016         r_texture_gammaramps = NULL;
4017         r_texture_numcubemaps = 0;
4018         r_uniformbufferalignment = 32;
4019
4020         r_loaddds = r_texture_dds_load.integer != 0;
4021         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4022
4023         switch(vid.renderpath)
4024         {
4025         case RENDERPATH_GL20:
4026         case RENDERPATH_D3D9:
4027         case RENDERPATH_D3D10:
4028         case RENDERPATH_D3D11:
4029         case RENDERPATH_SOFT:
4030         case RENDERPATH_GLES2:
4031                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032                 Cvar_SetValueQuick(&gl_combine, 1);
4033                 Cvar_SetValueQuick(&r_glsl, 1);
4034                 r_loadnormalmap = true;
4035                 r_loadgloss = true;
4036                 r_loadfog = false;
4037 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4038                 if (vid.support.arb_uniform_buffer_object)
4039                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4040 #endif
4041                         break;
4042         case RENDERPATH_GL13:
4043         case RENDERPATH_GLES1:
4044                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045                 Cvar_SetValueQuick(&gl_combine, 1);
4046                 Cvar_SetValueQuick(&r_glsl, 0);
4047                 r_loadnormalmap = false;
4048                 r_loadgloss = false;
4049                 r_loadfog = true;
4050                 break;
4051         case RENDERPATH_GL11:
4052                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053                 Cvar_SetValueQuick(&gl_combine, 0);
4054                 Cvar_SetValueQuick(&r_glsl, 0);
4055                 r_loadnormalmap = false;
4056                 r_loadgloss = false;
4057                 r_loadfog = true;
4058                 break;
4059         }
4060
4061         R_AnimCache_Free();
4062         R_FrameData_Reset();
4063         R_BufferData_Reset();
4064
4065         r_numqueries = 0;
4066         r_maxqueries = 0;
4067         memset(r_queries, 0, sizeof(r_queries));
4068
4069         r_qwskincache = NULL;
4070         r_qwskincache_size = 0;
4071
4072         // due to caching of texture_t references, the collision cache must be reset
4073         Collision_Cache_Reset(true);
4074
4075         // set up r_skinframe loading system for textures
4076         memset(&r_skinframe, 0, sizeof(r_skinframe));
4077         r_skinframe.loadsequence = 1;
4078         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4079
4080         r_main_texturepool = R_AllocTexturePool();
4081         R_BuildBlankTextures();
4082         R_BuildNoTexture();
4083         if (vid.support.arb_texture_cube_map)
4084         {
4085                 R_BuildWhiteCube();
4086                 R_BuildNormalizationCube();
4087         }
4088         r_texture_fogattenuation = NULL;
4089         r_texture_fogheighttexture = NULL;
4090         r_texture_gammaramps = NULL;
4091         //r_texture_fogintensity = NULL;
4092         memset(&r_fb, 0, sizeof(r_fb));
4093         r_glsl_permutation = NULL;
4094         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4096 #ifdef SUPPORTD3D
4097         r_hlsl_permutation = NULL;
4098         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4099         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4100 #endif
4101         memset(&r_svbsp, 0, sizeof (r_svbsp));
4102
4103         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4104         r_texture_numcubemaps = 0;
4105
4106         r_refdef.fogmasktable_density = 0;
4107
4108 #ifdef __ANDROID__
4109         // For Steelstorm Android
4110         // FIXME CACHE the program and reload
4111         // FIXME see possible combinations for SS:BR android
4112         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4113         R_SetupShader_SetPermutationGLSL(0, 12);
4114         R_SetupShader_SetPermutationGLSL(0, 13);
4115         R_SetupShader_SetPermutationGLSL(0, 8388621);
4116         R_SetupShader_SetPermutationGLSL(3, 0);
4117         R_SetupShader_SetPermutationGLSL(3, 2048);
4118         R_SetupShader_SetPermutationGLSL(5, 0);
4119         R_SetupShader_SetPermutationGLSL(5, 2);
4120         R_SetupShader_SetPermutationGLSL(5, 2048);
4121         R_SetupShader_SetPermutationGLSL(5, 8388608);
4122         R_SetupShader_SetPermutationGLSL(11, 1);
4123         R_SetupShader_SetPermutationGLSL(11, 2049);
4124         R_SetupShader_SetPermutationGLSL(11, 8193);
4125         R_SetupShader_SetPermutationGLSL(11, 10241);
4126         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4127 #endif
4128 }
4129
4130 static void gl_main_shutdown(void)
4131 {
4132         R_AnimCache_Free();
4133         R_FrameData_Reset();
4134         R_BufferData_Reset();
4135
4136         R_Main_FreeViewCache();
4137
4138         switch(vid.renderpath)
4139         {
4140         case RENDERPATH_GL11:
4141         case RENDERPATH_GL13:
4142         case RENDERPATH_GL20:
4143         case RENDERPATH_GLES1:
4144         case RENDERPATH_GLES2:
4145 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4146                 if (r_maxqueries)
4147                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4148 #endif
4149                 break;
4150         case RENDERPATH_D3D9:
4151                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4152                 break;
4153         case RENDERPATH_D3D10:
4154                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4155                 break;
4156         case RENDERPATH_D3D11:
4157                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4158                 break;
4159         case RENDERPATH_SOFT:
4160                 break;
4161         }
4162
4163         r_numqueries = 0;
4164         r_maxqueries = 0;
4165         memset(r_queries, 0, sizeof(r_queries));
4166
4167         r_qwskincache = NULL;
4168         r_qwskincache_size = 0;
4169
4170         // clear out the r_skinframe state
4171         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4172         memset(&r_skinframe, 0, sizeof(r_skinframe));
4173
4174         if (r_svbsp.nodes)
4175                 Mem_Free(r_svbsp.nodes);
4176         memset(&r_svbsp, 0, sizeof (r_svbsp));
4177         R_FreeTexturePool(&r_main_texturepool);
4178         loadingscreentexture = NULL;
4179         r_texture_blanknormalmap = NULL;
4180         r_texture_white = NULL;
4181         r_texture_grey128 = NULL;
4182         r_texture_black = NULL;
4183         r_texture_whitecube = NULL;
4184         r_texture_normalizationcube = NULL;
4185         r_texture_fogattenuation = NULL;
4186         r_texture_fogheighttexture = NULL;
4187         r_texture_gammaramps = NULL;
4188         r_texture_numcubemaps = 0;
4189         //r_texture_fogintensity = NULL;
4190         memset(&r_fb, 0, sizeof(r_fb));
4191         R_GLSL_Restart_f();
4192
4193         r_glsl_permutation = NULL;
4194         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4195         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4196 #ifdef SUPPORTD3D
4197         r_hlsl_permutation = NULL;
4198         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4199         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4200 #endif
4201 }
4202
4203 static void gl_main_newmap(void)
4204 {
4205         // FIXME: move this code to client
4206         char *entities, entname[MAX_QPATH];
4207         if (r_qwskincache)
4208                 Mem_Free(r_qwskincache);
4209         r_qwskincache = NULL;
4210         r_qwskincache_size = 0;
4211         if (cl.worldmodel)
4212         {
4213                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4214                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4215                 {
4216                         CL_ParseEntityLump(entities);
4217                         Mem_Free(entities);
4218                         return;
4219                 }
4220                 if (cl.worldmodel->brush.entities)
4221                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4222         }
4223         R_Main_FreeViewCache();
4224
4225         R_FrameData_Reset();
4226         R_BufferData_Reset();
4227 }
4228
4229 void GL_Main_Init(void)
4230 {
4231         int i;
4232         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4233         R_InitShaderModeInfo();
4234
4235         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4236         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4237         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4238         if (gamemode == GAME_NEHAHRA)
4239         {
4240                 Cvar_RegisterVariable (&gl_fogenable);
4241                 Cvar_RegisterVariable (&gl_fogdensity);
4242                 Cvar_RegisterVariable (&gl_fogred);
4243                 Cvar_RegisterVariable (&gl_foggreen);
4244                 Cvar_RegisterVariable (&gl_fogblue);
4245                 Cvar_RegisterVariable (&gl_fogstart);
4246                 Cvar_RegisterVariable (&gl_fogend);
4247                 Cvar_RegisterVariable (&gl_skyclip);
4248         }
4249         Cvar_RegisterVariable(&r_motionblur);
4250         Cvar_RegisterVariable(&r_damageblur);
4251         Cvar_RegisterVariable(&r_motionblur_averaging);
4252         Cvar_RegisterVariable(&r_motionblur_randomize);
4253         Cvar_RegisterVariable(&r_motionblur_minblur);
4254         Cvar_RegisterVariable(&r_motionblur_maxblur);
4255         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4256         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4257         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4258         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4259         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4260         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4261         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4262         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4263         Cvar_RegisterVariable(&r_equalize_entities_by);
4264         Cvar_RegisterVariable(&r_equalize_entities_to);
4265         Cvar_RegisterVariable(&r_depthfirst);
4266         Cvar_RegisterVariable(&r_useinfinitefarclip);
4267         Cvar_RegisterVariable(&r_farclip_base);
4268         Cvar_RegisterVariable(&r_farclip_world);
4269         Cvar_RegisterVariable(&r_nearclip);
4270         Cvar_RegisterVariable(&r_deformvertexes);
4271         Cvar_RegisterVariable(&r_transparent);
4272         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4273         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4274         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4275         Cvar_RegisterVariable(&r_showoverdraw);
4276         Cvar_RegisterVariable(&r_showbboxes);
4277         Cvar_RegisterVariable(&r_showbboxes_client);
4278         Cvar_RegisterVariable(&r_showsurfaces);
4279         Cvar_RegisterVariable(&r_showtris);
4280         Cvar_RegisterVariable(&r_shownormals);
4281         Cvar_RegisterVariable(&r_showlighting);
4282         Cvar_RegisterVariable(&r_showshadowvolumes);
4283         Cvar_RegisterVariable(&r_showcollisionbrushes);
4284         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4285         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4286         Cvar_RegisterVariable(&r_showdisabledepthtest);
4287         Cvar_RegisterVariable(&r_drawportals);
4288         Cvar_RegisterVariable(&r_drawentities);
4289         Cvar_RegisterVariable(&r_draw2d);
4290         Cvar_RegisterVariable(&r_drawworld);
4291         Cvar_RegisterVariable(&r_cullentities_trace);
4292         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4293         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4294         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4295         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4296         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4297         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4298         Cvar_RegisterVariable(&r_sortentities);
4299         Cvar_RegisterVariable(&r_drawviewmodel);
4300         Cvar_RegisterVariable(&r_drawexteriormodel);
4301         Cvar_RegisterVariable(&r_speeds);
4302         Cvar_RegisterVariable(&r_fullbrights);
4303         Cvar_RegisterVariable(&r_wateralpha);
4304         Cvar_RegisterVariable(&r_dynamic);
4305         Cvar_RegisterVariable(&r_fakelight);
4306         Cvar_RegisterVariable(&r_fakelight_intensity);
4307         Cvar_RegisterVariable(&r_fullbright_directed);
4308         Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4309         Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4310         Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4311         Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4312         Cvar_RegisterVariable(&r_fullbright);
4313         Cvar_RegisterVariable(&r_shadows);
4314         Cvar_RegisterVariable(&r_shadows_darken);
4315         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317         Cvar_RegisterVariable(&r_shadows_throwdistance);
4318         Cvar_RegisterVariable(&r_shadows_throwdirection);
4319         Cvar_RegisterVariable(&r_shadows_focus);
4320         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327         Cvar_RegisterVariable(&r_fog_exp2);
4328         Cvar_RegisterVariable(&r_fog_clear);
4329         Cvar_RegisterVariable(&r_drawfog);
4330         Cvar_RegisterVariable(&r_transparentdepthmasking);
4331         Cvar_RegisterVariable(&r_transparent_sortmindist);
4332         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334         Cvar_RegisterVariable(&r_texture_dds_load);
4335         Cvar_RegisterVariable(&r_texture_dds_save);
4336         Cvar_RegisterVariable(&r_textureunits);
4337         Cvar_RegisterVariable(&gl_combine);
4338         Cvar_RegisterVariable(&r_usedepthtextures);
4339         Cvar_RegisterVariable(&r_viewfbo);
4340         Cvar_RegisterVariable(&r_viewscale);
4341         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347         Cvar_RegisterVariable(&r_glsl);
4348         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357         Cvar_RegisterVariable(&r_glsl_postprocess);
4358         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366         Cvar_RegisterVariable(&r_celshading);
4367         Cvar_RegisterVariable(&r_celoutlines);
4368
4369         Cvar_RegisterVariable(&r_water);
4370         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4371         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4372         Cvar_RegisterVariable(&r_water_clippingplanebias);
4373         Cvar_RegisterVariable(&r_water_refractdistort);
4374         Cvar_RegisterVariable(&r_water_reflectdistort);
4375         Cvar_RegisterVariable(&r_water_scissormode);
4376         Cvar_RegisterVariable(&r_water_lowquality);
4377         Cvar_RegisterVariable(&r_water_hideplayer);
4378         Cvar_RegisterVariable(&r_water_fbo);
4379
4380         Cvar_RegisterVariable(&r_lerpsprites);
4381         Cvar_RegisterVariable(&r_lerpmodels);
4382         Cvar_RegisterVariable(&r_lerplightstyles);
4383         Cvar_RegisterVariable(&r_waterscroll);
4384         Cvar_RegisterVariable(&r_bloom);
4385         Cvar_RegisterVariable(&r_bloom_colorscale);
4386         Cvar_RegisterVariable(&r_bloom_brighten);
4387         Cvar_RegisterVariable(&r_bloom_blur);
4388         Cvar_RegisterVariable(&r_bloom_resolution);
4389         Cvar_RegisterVariable(&r_bloom_colorexponent);
4390         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4391         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4392         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4393         Cvar_RegisterVariable(&r_hdr_glowintensity);
4394         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4395         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4396         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4397         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4398         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4399         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4400         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4401         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4402         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4403         Cvar_RegisterVariable(&developer_texturelogging);
4404         Cvar_RegisterVariable(&gl_lightmaps);
4405         Cvar_RegisterVariable(&r_test);
4406         Cvar_RegisterVariable(&r_batch_multidraw);
4407         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4408         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4409         Cvar_RegisterVariable(&r_glsl_skeletal);
4410         Cvar_RegisterVariable(&r_glsl_saturation);
4411         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4412         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4413         Cvar_RegisterVariable(&r_framedatasize);
4414         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4415                 Cvar_RegisterVariable(&r_buffermegs[i]);
4416         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4417         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4418                 Cvar_SetValue("r_fullbrights", 0);
4419 #ifdef DP_MOBILETOUCH
4420         // GLES devices have terrible depth precision in general, so...
4421         Cvar_SetValueQuick(&r_nearclip, 4);
4422         Cvar_SetValueQuick(&r_farclip_base, 4096);
4423         Cvar_SetValueQuick(&r_farclip_world, 0);
4424         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4425 #endif
4426         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4427 }
4428
4429 void Render_Init(void)
4430 {
4431         gl_backend_init();
4432         R_Textures_Init();
4433         GL_Main_Init();
4434         Font_Init();
4435         GL_Draw_Init();
4436         R_Shadow_Init();
4437         R_Sky_Init();
4438         GL_Surf_Init();
4439         Sbar_Init();
4440         R_Particles_Init();
4441         R_Explosion_Init();
4442         R_LightningBeams_Init();
4443         Mod_RenderInit();
4444 }
4445
4446 /*
4447 ===============
4448 GL_Init
4449 ===============
4450 */
4451 #ifndef USE_GLES2
4452 extern char *ENGINE_EXTENSIONS;
4453 void GL_Init (void)
4454 {
4455         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4456         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4457         gl_version = (const char *)qglGetString(GL_VERSION);
4458         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4459
4460         if (!gl_extensions)
4461                 gl_extensions = "";
4462         if (!gl_platformextensions)
4463                 gl_platformextensions = "";
4464
4465         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4466         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4467         Con_Printf("GL_VERSION: %s\n", gl_version);
4468         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4469         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4470
4471         VID_CheckExtensions();
4472
4473         // LordHavoc: report supported extensions
4474 #ifdef CONFIG_MENU
4475         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4476 #else
4477         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4478 #endif
4479
4480         // clear to black (loading plaque will be seen over this)
4481         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4482 }
4483 #endif
4484
4485 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4486 {
4487         int i;
4488         mplane_t *p;
4489         if (r_trippy.integer)
4490                 return false;
4491         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4492         {
4493                 p = r_refdef.view.frustum + i;
4494                 switch(p->signbits)
4495                 {
4496                 default:
4497                 case 0:
4498                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499                                 return true;
4500                         break;
4501                 case 1:
4502                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 2:
4506                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 3:
4510                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 4:
4514                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 5:
4518                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 6:
4522                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 7:
4526                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 }
4530         }
4531         return false;
4532 }
4533
4534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4535 {
4536         int i;
4537         const mplane_t *p;
4538         if (r_trippy.integer)
4539                 return false;
4540         for (i = 0;i < numplanes;i++)
4541         {
4542                 p = planes + i;
4543                 switch(p->signbits)
4544                 {
4545                 default:
4546                 case 0:
4547                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4548                                 return true;
4549                         break;
4550                 case 1:
4551                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4552                                 return true;
4553                         break;
4554                 case 2:
4555                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4556                                 return true;
4557                         break;
4558                 case 3:
4559                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4560                                 return true;
4561                         break;
4562                 case 4:
4563                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 5:
4567                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 6:
4571                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 7:
4575                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 }
4579         }
4580         return false;
4581 }
4582
4583 //==================================================================================
4584
4585 // LordHavoc: this stores temporary data used within the same frame
4586
4587 typedef struct r_framedata_mem_s
4588 {
4589         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4590         size_t size; // how much usable space
4591         size_t current; // how much space in use
4592         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4593         size_t wantedsize; // how much space was allocated
4594         unsigned char *data; // start of real data (16byte aligned)
4595 }
4596 r_framedata_mem_t;
4597
4598 static r_framedata_mem_t *r_framedata_mem;
4599
4600 void R_FrameData_Reset(void)
4601 {
4602         while (r_framedata_mem)
4603         {
4604                 r_framedata_mem_t *next = r_framedata_mem->purge;
4605                 Mem_Free(r_framedata_mem);
4606                 r_framedata_mem = next;
4607         }
4608 }
4609
4610 static void R_FrameData_Resize(qboolean mustgrow)
4611 {
4612         size_t wantedsize;
4613         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4614         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4615         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4616         {
4617                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4618                 newmem->wantedsize = wantedsize;
4619                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4620                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4621                 newmem->current = 0;
4622                 newmem->mark = 0;
4623                 newmem->purge = r_framedata_mem;
4624                 r_framedata_mem = newmem;
4625         }
4626 }
4627
4628 void R_FrameData_NewFrame(void)
4629 {
4630         R_FrameData_Resize(false);
4631         if (!r_framedata_mem)
4632                 return;
4633         // if we ran out of space on the last frame, free the old memory now
4634         while (r_framedata_mem->purge)
4635         {
4636                 // repeatedly remove the second item in the list, leaving only head
4637                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4638                 Mem_Free(r_framedata_mem->purge);
4639                 r_framedata_mem->purge = next;
4640         }
4641         // reset the current mem pointer
4642         r_framedata_mem->current = 0;
4643         r_framedata_mem->mark = 0;
4644 }
4645
4646 void *R_FrameData_Alloc(size_t size)
4647 {
4648         void *data;
4649         float newvalue;
4650
4651         // align to 16 byte boundary - the data pointer is already aligned, so we
4652         // only need to ensure the size of every allocation is also aligned
4653         size = (size + 15) & ~15;
4654
4655         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4656         {
4657                 // emergency - we ran out of space, allocate more memory
4658                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4659                 newvalue = r_framedatasize.value * 2.0f;
4660                 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4661                 if (sizeof(size_t) >= 8)
4662                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4663                 else
4664                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4665                 // this might not be a growing it, but we'll allocate another buffer every time
4666                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4667                 R_FrameData_Resize(true);
4668         }
4669
4670         data = r_framedata_mem->data + r_framedata_mem->current;
4671         r_framedata_mem->current += size;
4672
4673         // count the usage for stats
4674         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4675         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4676
4677         return (void *)data;
4678 }
4679
4680 void *R_FrameData_Store(size_t size, void *data)
4681 {
4682         void *d = R_FrameData_Alloc(size);
4683         if (d && data)
4684                 memcpy(d, data, size);
4685         return d;
4686 }
4687
4688 void R_FrameData_SetMark(void)
4689 {
4690         if (!r_framedata_mem)
4691                 return;
4692         r_framedata_mem->mark = r_framedata_mem->current;
4693 }
4694
4695 void R_FrameData_ReturnToMark(void)
4696 {
4697         if (!r_framedata_mem)
4698                 return;
4699         r_framedata_mem->current = r_framedata_mem->mark;
4700 }
4701
4702 //==================================================================================
4703
4704 // avoid reusing the same buffer objects on consecutive frames
4705 #define R_BUFFERDATA_CYCLE 3
4706
4707 typedef struct r_bufferdata_buffer_s
4708 {
4709         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4710         size_t size; // how much usable space
4711         size_t current; // how much space in use
4712         r_meshbuffer_t *buffer; // the buffer itself
4713 }
4714 r_bufferdata_buffer_t;
4715
4716 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4717 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4718
4719 /// frees all dynamic buffers
4720 void R_BufferData_Reset(void)
4721 {
4722         int cycle, type;
4723         r_bufferdata_buffer_t **p, *mem;
4724         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4725         {
4726                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4727                 {
4728                         // free all buffers
4729                         p = &r_bufferdata_buffer[cycle][type];
4730                         while (*p)
4731                         {
4732                                 mem = *p;
4733                                 *p = (*p)->purge;
4734                                 if (mem->buffer)
4735                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4736                                 Mem_Free(mem);
4737                         }
4738                 }
4739         }
4740 }
4741
4742 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4743 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4744 {
4745         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4746         size_t size;
4747         float newvalue = r_buffermegs[type].value;
4748
4749         // increase the cvar if we have to (but only if we already have a mem)
4750         if (mustgrow && mem)
4751                 newvalue *= 2.0f;
4752         newvalue = bound(0.25f, newvalue, 256.0f);
4753         while (newvalue * 1024*1024 < minsize)
4754                 newvalue *= 2.0f;
4755
4756         // clamp the cvar to valid range
4757         newvalue = bound(0.25f, newvalue, 256.0f);
4758         if (r_buffermegs[type].value != newvalue)
4759                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4760
4761         // calculate size in bytes
4762         size = (size_t)(newvalue * 1024*1024);
4763         size = bound(131072, size, 256*1024*1024);
4764
4765         // allocate a new buffer if the size is different (purge old one later)
4766         // or if we were told we must grow the buffer
4767         if (!mem || mem->size != size || mustgrow)
4768         {
4769                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4770                 mem->size = size;
4771                 mem->current = 0;
4772                 if (type == R_BUFFERDATA_VERTEX)
4773                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4774                 else if (type == R_BUFFERDATA_INDEX16)
4775                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4776                 else if (type == R_BUFFERDATA_INDEX32)
4777                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4778                 else if (type == R_BUFFERDATA_UNIFORM)
4779                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4780                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4782         }
4783 }
4784
4785 void R_BufferData_NewFrame(void)
4786 {
4787         int type;
4788         r_bufferdata_buffer_t **p, *mem;
4789         // cycle to the next frame's buffers
4790         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4791         // if we ran out of space on the last time we used these buffers, free the old memory now
4792         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4793         {
4794                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4795                 {
4796                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4797                         // free all but the head buffer, this is how we recycle obsolete
4798                         // buffers after they are no longer in use
4799                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4800                         while (*p)
4801                         {
4802                                 mem = *p;
4803                                 *p = (*p)->purge;
4804                                 if (mem->buffer)
4805                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4806                                 Mem_Free(mem);
4807                         }
4808                         // reset the current offset
4809                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4810                 }
4811         }
4812 }
4813
4814 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4815 {
4816         r_bufferdata_buffer_t *mem;
4817         int offset = 0;
4818         int padsize;
4819
4820         *returnbufferoffset = 0;
4821
4822         // align size to a byte boundary appropriate for the buffer type, this
4823         // makes all allocations have aligned start offsets
4824         if (type == R_BUFFERDATA_UNIFORM)
4825                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4826         else
4827                 padsize = (datasize + 15) & ~15;
4828
4829         // if we ran out of space in this buffer we must allocate a new one
4830         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4831                 R_BufferData_Resize(type, true, padsize);
4832
4833         // if the resize did not give us enough memory, fail
4834         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4835                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4836
4837         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4838         offset = (int)mem->current;
4839         mem->current += padsize;
4840
4841         // upload the data to the buffer at the chosen offset
4842         if (offset == 0)
4843                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4844         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4845
4846         // count the usage for stats
4847         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4848         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4849
4850         // return the buffer offset
4851         *returnbufferoffset = offset;
4852
4853         return mem->buffer;
4854 }
4855
4856 //==================================================================================
4857
4858 // LordHavoc: animcache originally written by Echon, rewritten since then
4859
4860 /**
4861  * Animation cache prevents re-generating mesh data for an animated model
4862  * multiple times in one frame for lighting, shadowing, reflections, etc.
4863  */
4864
4865 void R_AnimCache_Free(void)
4866 {
4867 }
4868
4869 void R_AnimCache_ClearCache(void)
4870 {
4871         int i;
4872         entity_render_t *ent;
4873
4874         for (i = 0;i < r_refdef.scene.numentities;i++)
4875         {
4876                 ent = r_refdef.scene.entities[i];
4877                 ent->animcache_vertex3f = NULL;
4878                 ent->animcache_vertex3f_vertexbuffer = NULL;
4879                 ent->animcache_vertex3f_bufferoffset = 0;
4880                 ent->animcache_normal3f = NULL;
4881                 ent->animcache_normal3f_vertexbuffer = NULL;
4882                 ent->animcache_normal3f_bufferoffset = 0;
4883                 ent->animcache_svector3f = NULL;
4884                 ent->animcache_svector3f_vertexbuffer = NULL;
4885                 ent->animcache_svector3f_bufferoffset = 0;
4886                 ent->animcache_tvector3f = NULL;
4887                 ent->animcache_tvector3f_vertexbuffer = NULL;
4888                 ent->animcache_tvector3f_bufferoffset = 0;
4889                 ent->animcache_vertexmesh = NULL;
4890                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4891                 ent->animcache_vertexmesh_bufferoffset = 0;
4892                 ent->animcache_skeletaltransform3x4 = NULL;
4893                 ent->animcache_skeletaltransform3x4buffer = NULL;
4894                 ent->animcache_skeletaltransform3x4offset = 0;
4895                 ent->animcache_skeletaltransform3x4size = 0;
4896         }
4897 }
4898
4899 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4900 {
4901         int i;
4902
4903         // check if we need the meshbuffers
4904         if (!vid.useinterleavedarrays)
4905                 return;
4906
4907         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4908                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4909         // TODO: upload vertexbuffer?
4910         if (ent->animcache_vertexmesh)
4911         {
4912                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4913                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4914                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4915                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4916                 for (i = 0;i < numvertices;i++)
4917                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4918                 if (ent->animcache_svector3f)
4919                         for (i = 0;i < numvertices;i++)
4920                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4921                 if (ent->animcache_tvector3f)
4922                         for (i = 0;i < numvertices;i++)
4923                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4924                 if (ent->animcache_normal3f)
4925                         for (i = 0;i < numvertices;i++)
4926                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4927         }
4928 }
4929
4930 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4931 {
4932         dp_model_t *model = ent->model;
4933         int numvertices;
4934
4935         // see if this ent is worth caching
4936         if (!model || !model->Draw || !model->AnimateVertices)
4937                 return false;
4938         // nothing to cache if it contains no animations and has no skeleton
4939         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4940                 return false;
4941         // see if it is already cached for gpuskeletal
4942         if (ent->animcache_skeletaltransform3x4)
4943                 return false;
4944         // see if it is already cached as a mesh
4945         if (ent->animcache_vertex3f)
4946         {
4947                 // check if we need to add normals or tangents
4948                 if (ent->animcache_normal3f)
4949                         wantnormals = false;
4950                 if (ent->animcache_svector3f)
4951                         wanttangents = false;
4952                 if (!wantnormals && !wanttangents)
4953                         return false;
4954         }
4955
4956         // check which kind of cache we need to generate
4957         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4958         {
4959                 // cache the skeleton so the vertex shader can use it
4960                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4961                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4962                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4963                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4964                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4965                 // note: this can fail if the buffer is at the grow limit
4966                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4967                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4968         }
4969         else if (ent->animcache_vertex3f)
4970         {
4971                 // mesh was already cached but we may need to add normals/tangents
4972                 // (this only happens with multiple views, reflections, cameras, etc)
4973                 if (wantnormals || wanttangents)
4974                 {
4975                         numvertices = model->surfmesh.num_vertices;
4976                         if (wantnormals)
4977                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4978                         if (wanttangents)
4979                         {
4980                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982                         }
4983                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4984                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4986                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4987                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4988                 }
4989         }
4990         else
4991         {
4992                 // generate mesh cache
4993                 numvertices = model->surfmesh.num_vertices;
4994                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4995                 if (wantnormals)
4996                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4997                 if (wanttangents)
4998                 {
4999                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001                 }
5002                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5003                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5004                 if (wantnormals || wanttangents)
5005                 {
5006                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5009                 }
5010                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5011                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5012                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5013         }
5014         return true;
5015 }
5016
5017 void R_AnimCache_CacheVisibleEntities(void)
5018 {
5019         int i;
5020         qboolean wantnormals = true;
5021         qboolean wanttangents = !r_showsurfaces.integer;
5022
5023         switch(vid.renderpath)
5024         {
5025         case RENDERPATH_GL20:
5026         case RENDERPATH_D3D9:
5027         case RENDERPATH_D3D10:
5028         case RENDERPATH_D3D11:
5029         case RENDERPATH_GLES2:
5030                 break;
5031         case RENDERPATH_GL11:
5032         case RENDERPATH_GL13:
5033         case RENDERPATH_GLES1:
5034                 wanttangents = false;
5035                 break;
5036         case RENDERPATH_SOFT:
5037                 break;
5038         }
5039
5040         if (r_shownormals.integer)
5041                 wanttangents = wantnormals = true;
5042
5043         // TODO: thread this
5044         // NOTE: R_PrepareRTLights() also caches entities
5045
5046         for (i = 0;i < r_refdef.scene.numentities;i++)
5047                 if (r_refdef.viewcache.entityvisible[i])
5048                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5049 }
5050
5051 //==================================================================================
5052
5053 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5054 {
5055         int i;
5056         vec3_t eyemins, eyemaxs;
5057         vec3_t boxmins, boxmaxs;
5058         vec3_t start;
5059         vec3_t end;
5060         dp_model_t *model = r_refdef.scene.worldmodel;
5061         static vec3_t positions[] = {
5062                 { 0.5f, 0.5f, 0.5f },
5063                 { 0.0f, 0.0f, 0.0f },
5064                 { 0.0f, 0.0f, 1.0f },
5065                 { 0.0f, 1.0f, 0.0f },
5066                 { 0.0f, 1.0f, 1.0f },
5067                 { 1.0f, 0.0f, 0.0f },
5068                 { 1.0f, 0.0f, 1.0f },
5069                 { 1.0f, 1.0f, 0.0f },
5070                 { 1.0f, 1.0f, 1.0f },
5071         };
5072
5073         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5074         if (numsamples < 0)
5075                 return true;
5076
5077         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5078         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5079                 return true;
5080
5081         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5082                 return true;
5083
5084         // expand the eye box a little
5085         eyemins[0] = eye[0] - eyejitter;
5086         eyemaxs[0] = eye[0] + eyejitter;
5087         eyemins[1] = eye[1] - eyejitter;
5088         eyemaxs[1] = eye[1] + eyejitter;
5089         eyemins[2] = eye[2] - eyejitter;
5090         eyemaxs[2] = eye[2] + eyejitter;
5091         // expand the box a little
5092         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5093         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5094         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5095         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5096         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5097         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5098
5099         // return true if eye overlaps enlarged box
5100         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5101                 return true;
5102
5103         // try specific positions in the box first - note that these can be cached
5104         if (r_cullentities_trace_entityocclusion.integer)
5105         {
5106                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5107                 {
5108                         VectorCopy(eye, start);
5109                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5110                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5111                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5112                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5113                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5114                         // not picky - if the trace ended anywhere in the box we're good
5115                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5116                                 return true;
5117                 }
5118         }
5119         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5120                 return true;
5121
5122         // try various random positions
5123         for (i = 0; i < numsamples; i++)
5124         {
5125                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5126                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5127                 if (r_cullentities_trace_entityocclusion.integer)
5128                 {
5129                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5130                         // not picky - if the trace ended anywhere in the box we're good
5131                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5132                                 return true;
5133                 }
5134                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5135                         return true;
5136         }
5137
5138         return false;
5139 }
5140
5141
5142 static void R_View_UpdateEntityVisible (void)
5143 {
5144         int i;
5145         int renderimask;
5146         int samples;
5147         entity_render_t *ent;
5148
5149         if (r_refdef.envmap || r_fb.water.hideplayer)
5150                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5151         else if (chase_active.integer || r_fb.water.renderingscene)
5152                 renderimask = RENDER_VIEWMODEL;
5153         else
5154                 renderimask = RENDER_EXTERIORMODEL;
5155         if (!r_drawviewmodel.integer)
5156                 renderimask |= RENDER_VIEWMODEL;
5157         if (!r_drawexteriormodel.integer)
5158                 renderimask |= RENDER_EXTERIORMODEL;
5159         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5160         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5161         {
5162                 // worldmodel can check visibility
5163                 for (i = 0;i < r_refdef.scene.numentities;i++)
5164                 {
5165                         ent = r_refdef.scene.entities[i];
5166                         if (!(ent->flags & renderimask))
5167                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5168                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5169                                 r_refdef.viewcache.entityvisible[i] = true;
5170                 }
5171         }
5172         else
5173         {
5174                 // no worldmodel or it can't check visibility
5175                 for (i = 0;i < r_refdef.scene.numentities;i++)
5176                 {
5177                         ent = r_refdef.scene.entities[i];
5178                         if (!(ent->flags & renderimask))
5179                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5180                                 r_refdef.viewcache.entityvisible[i] = true;
5181                 }
5182         }
5183         if (r_cullentities_trace.integer)
5184         {
5185                 for (i = 0;i < r_refdef.scene.numentities;i++)
5186                 {
5187                         if (!r_refdef.viewcache.entityvisible[i])
5188                                 continue;
5189                         ent = r_refdef.scene.entities[i];
5190                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5191                         {
5192                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5193                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5194                                         ent->last_trace_visibility = realtime;
5195                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5196                                         r_refdef.viewcache.entityvisible[i] = 0;
5197                         }
5198                 }
5199         }
5200 }
5201
5202 /// only used if skyrendermasked, and normally returns false
5203 static int R_DrawBrushModelsSky (void)
5204 {
5205         int i, sky;
5206         entity_render_t *ent;
5207
5208         sky = false;
5209         for (i = 0;i < r_refdef.scene.numentities;i++)
5210         {
5211                 if (!r_refdef.viewcache.entityvisible[i])
5212                         continue;
5213                 ent = r_refdef.scene.entities[i];
5214                 if (!ent->model || !ent->model->DrawSky)
5215                         continue;
5216                 ent->model->DrawSky(ent);
5217                 sky = true;
5218         }
5219         return sky;
5220 }
5221
5222 static void R_DrawNoModel(entity_render_t *ent);
5223 static void R_DrawModels(void)
5224 {
5225         int i;
5226         entity_render_t *ent;
5227
5228         for (i = 0;i < r_refdef.scene.numentities;i++)
5229         {
5230                 if (!r_refdef.viewcache.entityvisible[i])
5231                         continue;
5232                 ent = r_refdef.scene.entities[i];
5233                 r_refdef.stats[r_stat_entities]++;
5234                 /*
5235                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5236                 {
5237                         vec3_t f, l, u, o;
5238                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5239                         Con_Printf("R_DrawModels\n");
5240                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5241                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5242                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5243                 }
5244                 */
5245                 if (ent->model && ent->model->Draw != NULL)
5246                         ent->model->Draw(ent);
5247                 else
5248                         R_DrawNoModel(ent);
5249         }
5250 }
5251
5252 static void R_DrawModelsDepth(void)
5253 {
5254         int i;
5255         entity_render_t *ent;
5256
5257         for (i = 0;i < r_refdef.scene.numentities;i++)
5258         {
5259                 if (!r_refdef.viewcache.entityvisible[i])
5260                         continue;
5261                 ent = r_refdef.scene.entities[i];
5262                 if (ent->model && ent->model->DrawDepth != NULL)
5263                         ent->model->DrawDepth(ent);
5264         }
5265 }
5266
5267 static void R_DrawModelsDebug(void)
5268 {
5269         int i;
5270         entity_render_t *ent;
5271
5272         for (i = 0;i < r_refdef.scene.numentities;i++)
5273         {
5274                 if (!r_refdef.viewcache.entityvisible[i])
5275                         continue;
5276                 ent = r_refdef.scene.entities[i];
5277                 if (ent->model && ent->model->DrawDebug != NULL)
5278                         ent->model->DrawDebug(ent);
5279         }
5280 }
5281
5282 static void R_DrawModelsAddWaterPlanes(void)
5283 {
5284         int i;
5285         entity_render_t *ent;
5286
5287         for (i = 0;i < r_refdef.scene.numentities;i++)
5288         {
5289                 if (!r_refdef.viewcache.entityvisible[i])
5290                         continue;
5291                 ent = r_refdef.scene.entities[i];
5292                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5293                         ent->model->DrawAddWaterPlanes(ent);
5294         }
5295 }
5296
5297 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5298
5299 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5300 {
5301         if (r_hdr_irisadaptation.integer)
5302         {
5303                 vec3_t p;
5304                 vec3_t ambient;
5305                 vec3_t diffuse;
5306                 vec3_t diffusenormal;
5307                 vec3_t forward;
5308                 vec_t brightness = 0.0f;
5309                 vec_t goal;
5310                 vec_t current;
5311                 vec_t d;
5312                 int c;
5313                 VectorCopy(r_refdef.view.forward, forward);
5314                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5315                 {
5316                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5317                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5318                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5319                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5320                         d = DotProduct(forward, diffusenormal);
5321                         brightness += VectorLength(ambient);
5322                         if (d > 0)
5323                                 brightness += d * VectorLength(diffuse);
5324                 }
5325                 brightness *= 1.0f / c;
5326                 brightness += 0.00001f; // make sure it's never zero
5327                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5328                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5329                 current = r_hdr_irisadaptation_value.value;
5330                 if (current < goal)
5331                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5332                 else if (current > goal)
5333                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5334                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5335                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5336         }
5337         else if (r_hdr_irisadaptation_value.value != 1.0f)
5338                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5339 }
5340
5341 static void R_View_SetFrustum(const int *scissor)
5342 {
5343         int i;
5344         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5345         vec3_t forward, left, up, origin, v;
5346
5347         if(scissor)
5348         {
5349                 // flipped x coordinates (because x points left here)
5350                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5351                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5352
5353                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5354                 switch(vid.renderpath)
5355                 {
5356                         case RENDERPATH_D3D9:
5357                         case RENDERPATH_D3D10:
5358                         case RENDERPATH_D3D11:
5359                                 // non-flipped y coordinates
5360                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5362                                 break;
5363                         case RENDERPATH_SOFT:
5364                         case RENDERPATH_GL11:
5365                         case RENDERPATH_GL13:
5366                         case RENDERPATH_GL20:
5367                         case RENDERPATH_GLES1:
5368                         case RENDERPATH_GLES2:
5369                                 // non-flipped y coordinates
5370                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5371                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5372                                 break;
5373                 }
5374         }
5375
5376         // we can't trust r_refdef.view.forward and friends in reflected scenes
5377         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5378
5379 #if 0
5380         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5381         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5382         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5383         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5384         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5385         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5386         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5387         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5388         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5389         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5390         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5391         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5392 #endif
5393
5394 #if 0
5395         zNear = r_refdef.nearclip;
5396         nudge = 1.0 - 1.0 / (1<<23);
5397         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5398         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5399         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5400         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5401         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5402         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5403         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5404         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5405 #endif
5406
5407
5408
5409 #if 0
5410         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5411         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5412         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5413         r_refdef.view.frustum[0].dist = m[15] - m[12];
5414
5415         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5416         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5417         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5418         r_refdef.view.frustum[1].dist = m[15] + m[12];
5419
5420         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5421         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5422         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5423         r_refdef.view.frustum[2].dist = m[15] - m[13];
5424
5425         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5426         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5427         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5428         r_refdef.view.frustum[3].dist = m[15] + m[13];
5429
5430         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5431         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5432         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5433         r_refdef.view.frustum[4].dist = m[15] - m[14];
5434
5435         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5436         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5437         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5438         r_refdef.view.frustum[5].dist = m[15] + m[14];
5439 #endif
5440
5441         if (r_refdef.view.useperspective)
5442         {
5443                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5444                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5445                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5446                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5447                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5448
5449                 // then the normals from the corners relative to origin
5450                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5451                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5452                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5453                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5454
5455                 // in a NORMAL view, forward cross left == up
5456                 // in a REFLECTED view, forward cross left == down
5457                 // so our cross products above need to be adjusted for a left handed coordinate system
5458                 CrossProduct(forward, left, v);
5459                 if(DotProduct(v, up) < 0)
5460                 {
5461                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5462                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5463                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5464                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5465                 }
5466
5467                 // Leaving those out was a mistake, those were in the old code, and they
5468                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5469                 // I couldn't reproduce it after adding those normalizations. --blub
5470                 VectorNormalize(r_refdef.view.frustum[0].normal);
5471                 VectorNormalize(r_refdef.view.frustum[1].normal);
5472                 VectorNormalize(r_refdef.view.frustum[2].normal);
5473                 VectorNormalize(r_refdef.view.frustum[3].normal);
5474
5475                 // make the corners absolute
5476                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5477                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5478                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5479                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5480
5481                 // one more normal
5482                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5483
5484                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5485                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5486                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5487                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5488                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5489         }
5490         else
5491         {
5492                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5493                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5494                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5495                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5496                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5497                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5498                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5499                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5500                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5501                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5502         }
5503         r_refdef.view.numfrustumplanes = 5;
5504
5505         if (r_refdef.view.useclipplane)
5506         {
5507                 r_refdef.view.numfrustumplanes = 6;
5508                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5509         }
5510
5511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5512                 PlaneClassify(r_refdef.view.frustum + i);
5513
5514         // LordHavoc: note to all quake engine coders, Quake had a special case
5515         // for 90 degrees which assumed a square view (wrong), so I removed it,
5516         // Quake2 has it disabled as well.
5517
5518         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5519         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5520         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5521         //PlaneClassify(&frustum[0]);
5522
5523         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5524         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5525         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5526         //PlaneClassify(&frustum[1]);
5527
5528         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5529         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5530         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5531         //PlaneClassify(&frustum[2]);
5532
5533         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5534         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5535         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5536         //PlaneClassify(&frustum[3]);
5537
5538         // nearclip plane
5539         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5540         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5541         //PlaneClassify(&frustum[4]);
5542 }
5543
5544 static void R_View_UpdateWithScissor(const int *myscissor)
5545 {
5546         R_Main_ResizeViewCache();
5547         R_View_SetFrustum(myscissor);
5548         R_View_WorldVisibility(r_refdef.view.useclipplane);
5549         R_View_UpdateEntityVisible();
5550 }
5551
5552 static void R_View_Update(void)
5553 {
5554         R_Main_ResizeViewCache();
5555         R_View_SetFrustum(NULL);
5556         R_View_WorldVisibility(r_refdef.view.useclipplane);
5557         R_View_UpdateEntityVisible();
5558 }
5559
5560 float viewscalefpsadjusted = 1.0f;
5561
5562 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5563 {
5564         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5565         scale = bound(0.03125f, scale, 1.0f);
5566         *outwidth = (int)ceil(width * scale);
5567         *outheight = (int)ceil(height * scale);
5568 }
5569
5570 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5571 {
5572         const float *customclipplane = NULL;
5573         float plane[4];
5574         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5575         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5576         {
5577                 // LordHavoc: couldn't figure out how to make this approach the
5578                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5579                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5580                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5581                         dist = r_refdef.view.clipplane.dist;
5582                 plane[0] = r_refdef.view.clipplane.normal[0];
5583                 plane[1] = r_refdef.view.clipplane.normal[1];
5584                 plane[2] = r_refdef.view.clipplane.normal[2];
5585                 plane[3] = -dist;
5586                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5587         }
5588
5589         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5590         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5591
5592         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5593         if (!r_refdef.view.useperspective)
5594                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5595         else if (vid.stencil && r_useinfinitefarclip.integer)
5596                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5597         else
5598                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5599         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5600         R_SetViewport(&r_refdef.view.viewport);
5601         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5602         {
5603                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5604                 float screenplane[4];
5605                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5606                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5607                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5608                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5609                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5610         }
5611 }
5612
5613 void R_EntityMatrix(const matrix4x4_t *matrix)
5614 {
5615         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5616         {
5617                 gl_modelmatrixchanged = false;
5618                 gl_modelmatrix = *matrix;
5619                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5620                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5621                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5622                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5623                 CHECKGLERROR
5624                 switch(vid.renderpath)
5625                 {
5626                 case RENDERPATH_D3D9:
5627 #ifdef SUPPORTD3D
5628                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5629                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5630 #endif
5631                         break;
5632                 case RENDERPATH_D3D10:
5633                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5634                         break;
5635                 case RENDERPATH_D3D11:
5636                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5637                         break;
5638                 case RENDERPATH_GL11:
5639                 case RENDERPATH_GL13:
5640                 case RENDERPATH_GLES1:
5641 #ifndef USE_GLES2
5642                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5643 #endif
5644                         break;
5645                 case RENDERPATH_SOFT:
5646                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5647                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5648                         break;
5649                 case RENDERPATH_GL20:
5650                 case RENDERPATH_GLES2:
5651                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5652                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5653                         break;
5654                 }
5655         }
5656 }
5657
5658 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5659 {
5660         r_viewport_t viewport;
5661
5662         CHECKGLERROR
5663
5664         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5665         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5666         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5667         R_SetViewport(&viewport);
5668         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5669         GL_Color(1, 1, 1, 1);
5670         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5671         GL_BlendFunc(GL_ONE, GL_ZERO);
5672         GL_ScissorTest(false);
5673         GL_DepthMask(false);
5674         GL_DepthRange(0, 1);
5675         GL_DepthTest(false);
5676         GL_DepthFunc(GL_LEQUAL);
5677         R_EntityMatrix(&identitymatrix);
5678         R_Mesh_ResetTextureState();
5679         GL_PolygonOffset(0, 0);
5680         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5681         switch(vid.renderpath)
5682         {
5683         case RENDERPATH_GL11:
5684         case RENDERPATH_GL13:
5685         case RENDERPATH_GL20:
5686         case RENDERPATH_GLES1:
5687         case RENDERPATH_GLES2:
5688                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5689                 break;
5690         case RENDERPATH_D3D9:
5691         case RENDERPATH_D3D10:
5692         case RENDERPATH_D3D11:
5693         case RENDERPATH_SOFT:
5694                 break;
5695         }
5696         GL_CullFace(GL_NONE);
5697
5698         CHECKGLERROR
5699 }
5700
5701 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5702 {
5703         DrawQ_Finish();
5704
5705         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5706 }
5707
5708 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5709 {
5710         DrawQ_Finish();
5711
5712         R_SetupView(true, fbo, depthtexture, colortexture);
5713         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5714         GL_Color(1, 1, 1, 1);
5715         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5716         GL_BlendFunc(GL_ONE, GL_ZERO);
5717         GL_ScissorTest(true);
5718         GL_DepthMask(true);
5719         GL_DepthRange(0, 1);
5720         GL_DepthTest(true);
5721         GL_DepthFunc(GL_LEQUAL);
5722         R_EntityMatrix(&identitymatrix);
5723         R_Mesh_ResetTextureState();
5724         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5725         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5726         switch(vid.renderpath)
5727         {
5728         case RENDERPATH_GL11:
5729         case RENDERPATH_GL13:
5730         case RENDERPATH_GL20:
5731         case RENDERPATH_GLES1:
5732         case RENDERPATH_GLES2:
5733                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5734                 break;
5735         case RENDERPATH_D3D9:
5736         case RENDERPATH_D3D10:
5737         case RENDERPATH_D3D11:
5738         case RENDERPATH_SOFT:
5739                 break;
5740         }
5741         GL_CullFace(r_refdef.view.cullface_back);
5742 }
5743
5744 /*
5745 ================
5746 R_RenderView_UpdateViewVectors
5747 ================
5748 */
5749 void R_RenderView_UpdateViewVectors(void)
5750 {
5751         // break apart the view matrix into vectors for various purposes
5752         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5753         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5754         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5755         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5756         // make an inverted copy of the view matrix for tracking sprites
5757         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5758 }
5759
5760 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5761 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5762
5763 static void R_Water_StartFrame(void)
5764 {
5765         int i;
5766         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5767         r_waterstate_waterplane_t *p;
5768         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5769
5770         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5771                 return;
5772
5773         switch(vid.renderpath)
5774         {
5775         case RENDERPATH_GL20:
5776         case RENDERPATH_D3D9:
5777         case RENDERPATH_D3D10:
5778         case RENDERPATH_D3D11:
5779         case RENDERPATH_SOFT:
5780         case RENDERPATH_GLES2:
5781                 break;
5782         case RENDERPATH_GL11:
5783         case RENDERPATH_GL13:
5784         case RENDERPATH_GLES1:
5785                 return;
5786         }
5787
5788         // set waterwidth and waterheight to the water resolution that will be
5789         // used (often less than the screen resolution for faster rendering)
5790         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5791
5792         // calculate desired texture sizes
5793         // can't use water if the card does not support the texture size
5794         if (!r_water.integer || r_showsurfaces.integer)
5795                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5796         else if (vid.support.arb_texture_non_power_of_two)
5797         {
5798                 texturewidth = waterwidth;
5799                 textureheight = waterheight;
5800                 camerawidth = waterwidth;
5801                 cameraheight = waterheight;
5802         }
5803         else
5804         {
5805                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5806                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5807                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5808                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5809         }
5810
5811         // allocate textures as needed
5812         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5813         {
5814                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5815                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5816                 {
5817                         if (p->texture_refraction)
5818                                 R_FreeTexture(p->texture_refraction);
5819                         p->texture_refraction = NULL;
5820                         if (p->fbo_refraction)
5821                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5822                         p->fbo_refraction = 0;
5823                         if (p->texture_reflection)
5824                                 R_FreeTexture(p->texture_reflection);
5825                         p->texture_reflection = NULL;
5826                         if (p->fbo_reflection)
5827                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5828                         p->fbo_reflection = 0;
5829                         if (p->texture_camera)
5830                                 R_FreeTexture(p->texture_camera);
5831                         p->texture_camera = NULL;
5832                         if (p->fbo_camera)
5833                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5834                         p->fbo_camera = 0;
5835                 }
5836                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5837                 r_fb.water.texturewidth = texturewidth;
5838                 r_fb.water.textureheight = textureheight;
5839                 r_fb.water.camerawidth = camerawidth;
5840                 r_fb.water.cameraheight = cameraheight;
5841         }
5842
5843         if (r_fb.water.texturewidth)
5844         {
5845                 int scaledwidth, scaledheight;
5846
5847                 r_fb.water.enabled = true;
5848
5849                 // water resolution is usually reduced
5850                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5851                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5852                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5853
5854                 // set up variables that will be used in shader setup
5855                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5856                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5857                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5858                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5859         }
5860
5861         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5862         r_fb.water.numwaterplanes = 0;
5863 }
5864
5865 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5866 {
5867         int planeindex, bestplaneindex, vertexindex;
5868         vec3_t mins, maxs, normal, center, v, n;
5869         vec_t planescore, bestplanescore;
5870         mplane_t plane;
5871         r_waterstate_waterplane_t *p;
5872         texture_t *t = R_GetCurrentTexture(surface->texture);
5873
5874         rsurface.texture = t;
5875         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5876         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5877         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5878                 return;
5879         // average the vertex normals, find the surface bounds (after deformvertexes)
5880         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5881         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5882         VectorCopy(n, normal);
5883         VectorCopy(v, mins);
5884         VectorCopy(v, maxs);
5885         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5886         {
5887                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5888                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5889                 VectorAdd(normal, n, normal);
5890                 mins[0] = min(mins[0], v[0]);
5891                 mins[1] = min(mins[1], v[1]);
5892                 mins[2] = min(mins[2], v[2]);
5893                 maxs[0] = max(maxs[0], v[0]);
5894                 maxs[1] = max(maxs[1], v[1]);
5895                 maxs[2] = max(maxs[2], v[2]);
5896         }
5897         VectorNormalize(normal);
5898         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5899
5900         VectorCopy(normal, plane.normal);
5901         VectorNormalize(plane.normal);
5902         plane.dist = DotProduct(center, plane.normal);
5903         PlaneClassify(&plane);
5904         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5905         {
5906                 // skip backfaces (except if nocullface is set)
5907 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5908 //                      return;
5909                 VectorNegate(plane.normal, plane.normal);
5910                 plane.dist *= -1;
5911                 PlaneClassify(&plane);
5912         }
5913
5914
5915         // find a matching plane if there is one
5916         bestplaneindex = -1;
5917         bestplanescore = 1048576.0f;
5918         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5919         {
5920                 if(p->camera_entity == t->camera_entity)
5921                 {
5922                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5923                         if (bestplaneindex < 0 || bestplanescore > planescore)
5924                         {
5925                                 bestplaneindex = planeindex;
5926                                 bestplanescore = planescore;
5927                         }
5928                 }
5929         }
5930         planeindex = bestplaneindex;
5931
5932         // if this surface does not fit any known plane rendered this frame, add one
5933         if (planeindex < 0 || bestplanescore > 0.001f)
5934         {
5935                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5936                 {
5937                         // store the new plane
5938                         planeindex = r_fb.water.numwaterplanes++;
5939                         p = r_fb.water.waterplanes + planeindex;
5940                         p->plane = plane;
5941                         // clear materialflags and pvs
5942                         p->materialflags = 0;
5943                         p->pvsvalid = false;
5944                         p->camera_entity = t->camera_entity;
5945                         VectorCopy(mins, p->mins);
5946                         VectorCopy(maxs, p->maxs);
5947                 }
5948                 else
5949                 {
5950                         // We're totally screwed.
5951                         return;
5952                 }
5953         }
5954         else
5955         {
5956                 // merge mins/maxs when we're adding this surface to the plane
5957                 p = r_fb.water.waterplanes + planeindex;
5958                 p->mins[0] = min(p->mins[0], mins[0]);
5959                 p->mins[1] = min(p->mins[1], mins[1]);
5960                 p->mins[2] = min(p->mins[2], mins[2]);
5961                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5962                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5963                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5964         }
5965         // merge this surface's materialflags into the waterplane
5966         p->materialflags |= t->currentmaterialflags;
5967         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5968         {
5969                 // merge this surface's PVS into the waterplane
5970                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5971                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5972                 {
5973                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5974                         p->pvsvalid = true;
5975                 }
5976         }
5977 }
5978
5979 extern cvar_t r_drawparticles;
5980 extern cvar_t r_drawdecals;
5981
5982 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5983 {
5984         int myscissor[4];
5985         r_refdef_view_t originalview;
5986         r_refdef_view_t myview;
5987         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5988         r_waterstate_waterplane_t *p;
5989         vec3_t visorigin;
5990         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5991         char vabuf[1024];
5992
5993         originalview = r_refdef.view;
5994
5995         // lowquality hack, temporarily shut down some cvars and restore afterwards
5996         qualityreduction = r_water_lowquality.integer;
5997         if (qualityreduction > 0)
5998         {
5999                 if (qualityreduction >= 1)
6000                 {
6001                         old_r_shadows = r_shadows.integer;
6002                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6003                         old_r_dlight = r_shadow_realtime_dlight.integer;
6004                         Cvar_SetValueQuick(&r_shadows, 0);
6005                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6006                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6007                 }
6008                 if (qualityreduction >= 2)
6009                 {
6010                         old_r_dynamic = r_dynamic.integer;
6011                         old_r_particles = r_drawparticles.integer;
6012                         old_r_decals = r_drawdecals.integer;
6013                         Cvar_SetValueQuick(&r_dynamic, 0);
6014                         Cvar_SetValueQuick(&r_drawparticles, 0);
6015                         Cvar_SetValueQuick(&r_drawdecals, 0);
6016                 }
6017         }
6018
6019         // make sure enough textures are allocated
6020         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6021         {
6022                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6023                         continue;
6024                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6025                 {
6026                         if (!p->texture_refraction)
6027                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6028                         if (!p->texture_refraction)
6029                                 goto error;
6030                         if (usewaterfbo)
6031                         {
6032                                 if (r_fb.water.depthtexture == NULL)
6033                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034                                 if (p->fbo_refraction == 0)
6035                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6036                         }
6037                 }
6038                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6039                 {
6040                         if (!p->texture_camera)
6041                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6042                         if (!p->texture_camera)
6043                                 goto error;
6044                         if (usewaterfbo)
6045                         {
6046                                 if (r_fb.water.depthtexture == NULL)
6047                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6048                                 if (p->fbo_camera == 0)
6049                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6050                         }
6051                 }
6052
6053                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6054                 {
6055                         if (!p->texture_reflection)
6056                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6057                         if (!p->texture_reflection)
6058                                 goto error;
6059                         if (usewaterfbo)
6060                         {
6061                                 if (r_fb.water.depthtexture == NULL)
6062                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6063                                 if (p->fbo_reflection == 0)
6064                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6065                         }
6066                 }
6067         }
6068
6069         // render views
6070         r_refdef.view = originalview;
6071         r_refdef.view.showdebug = false;
6072         r_refdef.view.width = r_fb.water.waterwidth;
6073         r_refdef.view.height = r_fb.water.waterheight;
6074         r_refdef.view.useclipplane = true;
6075         myview = r_refdef.view;
6076         r_fb.water.renderingscene = true;
6077         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6078         {
6079                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6080                         continue;
6081                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6082                 {
6083                         r_refdef.view = myview;
6084                         if(r_water_scissormode.integer)
6085                         {
6086                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6087                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6088                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6089                         }
6090
6091                         // render reflected scene and copy into texture
6092                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6093                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6094                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6095                         r_refdef.view.clipplane = p->plane;
6096                         // reverse the cullface settings for this render
6097                         r_refdef.view.cullface_front = GL_FRONT;
6098                         r_refdef.view.cullface_back = GL_BACK;
6099                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6100                         {
6101                                 r_refdef.view.usecustompvs = true;
6102                                 if (p->pvsvalid)
6103                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6104                                 else
6105                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6106                         }
6107
6108                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6109                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6110                         R_ClearScreen(r_refdef.fogenabled);
6111                         if(r_water_scissormode.integer & 2)
6112                                 R_View_UpdateWithScissor(myscissor);
6113                         else
6114                                 R_View_Update();
6115                         R_AnimCache_CacheVisibleEntities();
6116                         if(r_water_scissormode.integer & 1)
6117                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6118                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6119
6120                         if (!p->fbo_reflection)
6121                                 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6122                         r_fb.water.hideplayer = false;
6123                 }
6124
6125                 // render the normal view scene and copy into texture
6126                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
6127                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6128                 {
6129                         r_refdef.view = myview;
6130                         if(r_water_scissormode.integer)
6131                         {
6132                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6133                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6134                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6135                         }
6136
6137                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6138
6139                         r_refdef.view.clipplane = p->plane;
6140                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6141                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6142
6143                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6144                         {
6145                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6146                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6147                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6148                                 R_RenderView_UpdateViewVectors();
6149                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6150                                 {
6151                                         r_refdef.view.usecustompvs = true;
6152                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6153                                 }
6154                         }
6155
6156                         PlaneClassify(&r_refdef.view.clipplane);
6157
6158                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6159                         R_ClearScreen(r_refdef.fogenabled);
6160                         if(r_water_scissormode.integer & 2)
6161                                 R_View_UpdateWithScissor(myscissor);
6162                         else
6163                                 R_View_Update();
6164                         R_AnimCache_CacheVisibleEntities();
6165                         if(r_water_scissormode.integer & 1)
6166                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6167                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6168
6169                         if (!p->fbo_refraction)
6170                                 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6171                         r_fb.water.hideplayer = false;
6172                 }
6173                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6174                 {
6175                         r_refdef.view = myview;
6176
6177                         r_refdef.view.clipplane = p->plane;
6178                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6179                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6180
6181                         r_refdef.view.width = r_fb.water.camerawidth;
6182                         r_refdef.view.height = r_fb.water.cameraheight;
6183                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6184                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6185                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6186                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6187
6188                         if(p->camera_entity)
6189                         {
6190                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6191                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6192                         }
6193
6194                         // note: all of the view is used for displaying... so
6195                         // there is no use in scissoring
6196
6197                         // reverse the cullface settings for this render
6198                         r_refdef.view.cullface_front = GL_FRONT;
6199                         r_refdef.view.cullface_back = GL_BACK;
6200                         // also reverse the view matrix
6201                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
6202                         R_RenderView_UpdateViewVectors();
6203                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6204                         {
6205                                 r_refdef.view.usecustompvs = true;
6206                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6207                         }
6208                         
6209                         // camera needs no clipplane
6210                         r_refdef.view.useclipplane = false;
6211
6212                         PlaneClassify(&r_refdef.view.clipplane);
6213
6214                         r_fb.water.hideplayer = false;
6215
6216                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6217                         R_ClearScreen(r_refdef.fogenabled);
6218                         R_View_Update();
6219                         R_AnimCache_CacheVisibleEntities();
6220                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6221
6222                         if (!p->fbo_camera)
6223                                 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6224                         r_fb.water.hideplayer = false;
6225                 }
6226
6227         }
6228         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6229         r_fb.water.renderingscene = false;
6230         r_refdef.view = originalview;
6231         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6232         if (!r_fb.water.depthtexture)
6233                 R_ClearScreen(r_refdef.fogenabled);
6234         R_View_Update();
6235         R_AnimCache_CacheVisibleEntities();
6236         goto finish;
6237 error:
6238         r_refdef.view = originalview;
6239         r_fb.water.renderingscene = false;
6240         Cvar_SetValueQuick(&r_water, 0);
6241         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6242 finish:
6243         // lowquality hack, restore cvars
6244         if (qualityreduction > 0)
6245         {
6246                 if (qualityreduction >= 1)
6247                 {
6248                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6249                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6250                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6251                 }
6252                 if (qualityreduction >= 2)
6253                 {
6254                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6255                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6256                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6257                 }
6258         }
6259 }
6260
6261 static void R_Bloom_StartFrame(void)
6262 {
6263         int i;
6264         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6265         int viewwidth, viewheight;
6266         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6267         textype_t textype = TEXTYPE_COLORBUFFER;
6268
6269         switch (vid.renderpath)
6270         {
6271         case RENDERPATH_GL20:
6272                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6274                 {
6275                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6276                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6277                 }
6278                 break;
6279         case RENDERPATH_GL11:
6280         case RENDERPATH_GL13:
6281         case RENDERPATH_GLES1:
6282                 return; // don't bother
6283         case RENDERPATH_GLES2:
6284         case RENDERPATH_D3D9:
6285         case RENDERPATH_D3D10:
6286         case RENDERPATH_D3D11:
6287                 r_fb.usedepthtextures = false;
6288                 break;
6289         case RENDERPATH_SOFT:
6290                 r_fb.usedepthtextures = true;
6291                 break;
6292         }
6293
6294         if (r_viewscale_fpsscaling.integer)
6295         {
6296                 double actualframetime;
6297                 double targetframetime;
6298                 double adjust;
6299                 actualframetime = r_refdef.lastdrawscreentime;
6300                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6301                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6302                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6303                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6304                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6305                 viewscalefpsadjusted += adjust;
6306                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6307         }
6308         else
6309                 viewscalefpsadjusted = 1.0f;
6310
6311         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6312
6313         switch(vid.renderpath)
6314         {
6315         case RENDERPATH_GL20:
6316         case RENDERPATH_D3D9:
6317         case RENDERPATH_D3D10:
6318         case RENDERPATH_D3D11:
6319         case RENDERPATH_SOFT:
6320         case RENDERPATH_GLES2:
6321                 break;
6322         case RENDERPATH_GL11:
6323         case RENDERPATH_GL13:
6324         case RENDERPATH_GLES1:
6325                 return;
6326         }
6327
6328         // set bloomwidth and bloomheight to the bloom resolution that will be
6329         // used (often less than the screen resolution for faster rendering)
6330         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6331         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6332         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6333         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6334         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6335
6336         // calculate desired texture sizes
6337         if (vid.support.arb_texture_non_power_of_two)
6338         {
6339                 screentexturewidth = vid.width;
6340                 screentextureheight = vid.height;
6341                 bloomtexturewidth = r_fb.bloomwidth;
6342                 bloomtextureheight = r_fb.bloomheight;
6343         }
6344         else
6345         {
6346                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6347                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6348                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6349                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6350         }
6351
6352         if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6353         {
6354                 Cvar_SetValueQuick(&r_bloom, 0);
6355                 Cvar_SetValueQuick(&r_motionblur, 0);
6356                 Cvar_SetValueQuick(&r_damageblur, 0);
6357         }
6358
6359         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6360          && !r_bloom.integer
6361          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6362          && !useviewfbo
6363          && r_viewscale.value == 1.0f
6364          && !r_viewscale_fpsscaling.integer)
6365                 screentexturewidth = screentextureheight = 0;
6366         if (!r_bloom.integer)
6367                 bloomtexturewidth = bloomtextureheight = 0;
6368
6369         // allocate textures as needed
6370         if (r_fb.screentexturewidth != screentexturewidth
6371          || r_fb.screentextureheight != screentextureheight
6372          || r_fb.bloomtexturewidth != bloomtexturewidth
6373          || r_fb.bloomtextureheight != bloomtextureheight
6374          || r_fb.textype != textype
6375          || useviewfbo != (r_fb.fbo != 0))
6376         {
6377                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6378                 {
6379                         if (r_fb.bloomtexture[i])
6380                                 R_FreeTexture(r_fb.bloomtexture[i]);
6381                         r_fb.bloomtexture[i] = NULL;
6382
6383                         if (r_fb.bloomfbo[i])
6384                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6385                         r_fb.bloomfbo[i] = 0;
6386                 }
6387
6388                 if (r_fb.fbo)
6389                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6390                 r_fb.fbo = 0;
6391
6392                 if (r_fb.colortexture)
6393                         R_FreeTexture(r_fb.colortexture);
6394                 r_fb.colortexture = NULL;
6395
6396                 if (r_fb.depthtexture)
6397                         R_FreeTexture(r_fb.depthtexture);
6398                 r_fb.depthtexture = NULL;
6399
6400                 if (r_fb.ghosttexture)
6401                         R_FreeTexture(r_fb.ghosttexture);
6402                 r_fb.ghosttexture = NULL;
6403
6404                 r_fb.screentexturewidth = screentexturewidth;
6405                 r_fb.screentextureheight = screentextureheight;
6406                 r_fb.bloomtexturewidth = bloomtexturewidth;
6407                 r_fb.bloomtextureheight = bloomtextureheight;
6408                 r_fb.textype = textype;
6409
6410                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6411                 {
6412                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6413                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6414                         r_fb.ghosttexture_valid = false;
6415                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6416                         if (useviewfbo)
6417                         {
6418                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6419                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6420                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6421                         }
6422                 }
6423
6424                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6425                 {
6426                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6427                         {
6428                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6429                                 if (useviewfbo)
6430                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6431                         }
6432                 }
6433         }
6434
6435         // bloom texture is a different resolution
6436         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6437         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6438         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6439         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6440         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6441
6442         // set up a texcoord array for the full resolution screen image
6443         // (we have to keep this around to copy back during final render)
6444         r_fb.screentexcoord2f[0] = 0;
6445         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6446         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6447         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6448         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6449         r_fb.screentexcoord2f[5] = 0;
6450         r_fb.screentexcoord2f[6] = 0;
6451         r_fb.screentexcoord2f[7] = 0;
6452
6453         if(r_fb.fbo) 
6454         {
6455                 for (i = 1;i < 8;i += 2)
6456                 {
6457                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6458                 }
6459         }
6460
6461         // set up a texcoord array for the reduced resolution bloom image
6462         // (which will be additive blended over the screen image)
6463         r_fb.bloomtexcoord2f[0] = 0;
6464         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6465         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6466         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6467         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6468         r_fb.bloomtexcoord2f[5] = 0;
6469         r_fb.bloomtexcoord2f[6] = 0;
6470         r_fb.bloomtexcoord2f[7] = 0;
6471
6472         switch(vid.renderpath)
6473         {
6474         case RENDERPATH_GL11:
6475         case RENDERPATH_GL13:
6476         case RENDERPATH_GL20:
6477         case RENDERPATH_SOFT:
6478         case RENDERPATH_GLES1:
6479         case RENDERPATH_GLES2:
6480                 break;
6481         case RENDERPATH_D3D9:
6482         case RENDERPATH_D3D10:
6483         case RENDERPATH_D3D11:
6484                 for (i = 0;i < 4;i++)
6485                 {
6486                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6487                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6488                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6489                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6490                 }
6491                 break;
6492         }
6493
6494         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6495
6496         if (r_fb.fbo)
6497                 r_refdef.view.clear = true;
6498 }
6499
6500 static void R_Bloom_MakeTexture(void)
6501 {
6502         int x, range, dir;
6503         float xoffset, yoffset, r, brighten;
6504         rtexture_t *intex;
6505         float colorscale = r_bloom_colorscale.value;
6506
6507         r_refdef.stats[r_stat_bloom]++;
6508     
6509 #if 0
6510     // this copy is unnecessary since it happens in R_BlendView already
6511         if (!r_fb.fbo)
6512         {
6513                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6514                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6515         }
6516 #endif
6517
6518         // scale down screen texture to the bloom texture size
6519         CHECKGLERROR
6520         r_fb.bloomindex = 0;
6521         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6522         R_SetViewport(&r_fb.bloomviewport);
6523         GL_CullFace(GL_NONE);
6524         GL_DepthTest(false);
6525         GL_BlendFunc(GL_ONE, GL_ZERO);
6526         GL_Color(colorscale, colorscale, colorscale, 1);
6527         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6528         switch(vid.renderpath)
6529         {
6530         case RENDERPATH_GL11:
6531         case RENDERPATH_GL13:
6532         case RENDERPATH_GL20:
6533         case RENDERPATH_GLES1:
6534         case RENDERPATH_GLES2:
6535         case RENDERPATH_SOFT:
6536                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6537                 break;
6538         case RENDERPATH_D3D9:
6539         case RENDERPATH_D3D10:
6540         case RENDERPATH_D3D11:
6541                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6542                 break;
6543         }
6544         // TODO: do boxfilter scale-down in shader?
6545         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6546         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6548
6549         // we now have a properly scaled bloom image
6550         if (!r_fb.bloomfbo[r_fb.bloomindex])
6551         {
6552                 // copy it into the bloom texture
6553                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6554                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6555         }
6556
6557         // multiply bloom image by itself as many times as desired
6558         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6559         {
6560                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6561                 r_fb.bloomindex ^= 1;
6562                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6563                 x *= 2;
6564                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6565                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6566                 {
6567                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6568                         GL_Color(r,r,r,1); // apply fix factor
6569                 }
6570                 else
6571                 {
6572                         if(x <= 2)
6573                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6574                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6575                         GL_Color(1,1,1,1); // no fix factor supported here
6576                 }
6577                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6578                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6579                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6580                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6581
6582                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6583                 {
6584                         // copy the darkened image to a texture
6585                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6586                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6587                 }
6588         }
6589
6590         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6591         brighten = r_bloom_brighten.value;
6592         brighten = sqrt(brighten);
6593         if(range >= 1)
6594                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6595
6596         for (dir = 0;dir < 2;dir++)
6597         {
6598                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6599                 r_fb.bloomindex ^= 1;
6600                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6601                 // blend on at multiple vertical offsets to achieve a vertical blur
6602                 // TODO: do offset blends using GLSL
6603                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6604                 GL_BlendFunc(GL_ONE, GL_ZERO);
6605                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6606                 for (x = -range;x <= range;x++)
6607                 {
6608                         if (!dir){xoffset = 0;yoffset = x;}
6609                         else {xoffset = x;yoffset = 0;}
6610                         xoffset /= (float)r_fb.bloomtexturewidth;
6611                         yoffset /= (float)r_fb.bloomtextureheight;
6612                         // compute a texcoord array with the specified x and y offset
6613                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6614                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6615                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6616                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6617                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6618                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6619                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6620                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6621                         // this r value looks like a 'dot' particle, fading sharply to
6622                         // black at the edges
6623                         // (probably not realistic but looks good enough)
6624                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6625                         //r = brighten/(range*2+1);
6626                         r = brighten / (range * 2 + 1);
6627                         if(range >= 1)
6628                                 r *= (1 - x*x/(float)(range*range));
6629                         GL_Color(r, r, r, 1);
6630                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6631                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6632                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6633                         GL_BlendFunc(GL_ONE, GL_ONE);
6634                 }
6635
6636                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6637                 {
6638                         // copy the vertically or horizontally blurred bloom view to a texture
6639                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6640                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6641                 }
6642         }
6643 }
6644
6645 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6646 {
6647         dpuint64 permutation;
6648         float uservecs[4][4];
6649
6650         R_EntityMatrix(&identitymatrix);
6651
6652         switch (vid.renderpath)
6653         {
6654         case RENDERPATH_GL20:
6655         case RENDERPATH_D3D9:
6656         case RENDERPATH_D3D10:
6657         case RENDERPATH_D3D11:
6658         case RENDERPATH_SOFT:
6659         case RENDERPATH_GLES2:
6660                 permutation =
6661                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6662                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6663                         | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6664                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6665                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6666
6667                 if (r_fb.colortexture)
6668                 {
6669                         if (!r_fb.fbo)
6670                         {
6671                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6672                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6673                         }
6674
6675                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6676                         {
6677                                 // declare variables
6678                                 float blur_factor, blur_mouseaccel, blur_velocity;
6679                                 static float blur_average; 
6680                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6681
6682                                 // set a goal for the factoring
6683                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6684                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6685                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6686                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6687                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6688                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6689
6690                                 // from the goal, pick an averaged value between goal and last value
6691                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6692                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6693
6694                                 // enforce minimum amount of blur 
6695                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6696
6697                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6698
6699                                 // calculate values into a standard alpha
6700                                 cl.motionbluralpha = 1 - exp(-
6701                                                 (
6702                                                  (r_motionblur.value * blur_factor / 80)
6703                                                  +
6704                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6705                                                 )
6706                                                 /
6707                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6708                                           );
6709
6710                                 // randomization for the blur value to combat persistent ghosting
6711                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6712                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6713
6714                                 // apply the blur
6715                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6716                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6717                                 {
6718                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6720                                         switch(vid.renderpath)
6721                                         {
6722                                         case RENDERPATH_GL11:
6723                                         case RENDERPATH_GL13:
6724                                         case RENDERPATH_GL20:
6725                                         case RENDERPATH_GLES1:
6726                                         case RENDERPATH_GLES2:
6727                                         case RENDERPATH_SOFT:
6728                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6729                                                 break;
6730                                         case RENDERPATH_D3D9:
6731                                         case RENDERPATH_D3D10:
6732                                         case RENDERPATH_D3D11:
6733                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6734                                                 break;
6735                                         }
6736                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6737                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6738                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6739                                 }
6740
6741                                 // updates old view angles for next pass
6742                                 VectorCopy(cl.viewangles, blur_oldangles);
6743
6744                                 // copy view into the ghost texture
6745                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6746                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6747                                 r_fb.ghosttexture_valid = true;
6748                         }
6749                 }
6750                 else
6751                 {
6752                         // no r_fb.colortexture means we're rendering to the real fb
6753                         // we may still have to do view tint...
6754                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6755                         {
6756                                 // apply a color tint to the whole view
6757                                 R_ResetViewRendering2D(0, NULL, NULL);
6758                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6759                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6760                                 R_SetupShader_Generic_NoTexture(false, true);
6761                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6762                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6763                         }
6764                         break; // no screen processing, no bloom, skip it
6765                 }
6766
6767                 if (r_fb.bloomtexture[0])
6768                 {
6769                         // make the bloom texture
6770                         R_Bloom_MakeTexture();
6771                 }
6772
6773 #if _MSC_VER >= 1400
6774 #define sscanf sscanf_s
6775 #endif
6776                 memset(uservecs, 0, sizeof(uservecs));
6777                 if (r_glsl_postprocess_uservec1_enable.integer)
6778                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6779                 if (r_glsl_postprocess_uservec2_enable.integer)
6780                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6781                 if (r_glsl_postprocess_uservec3_enable.integer)
6782                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6783                 if (r_glsl_postprocess_uservec4_enable.integer)
6784                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6785
6786                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6787                 GL_Color(1, 1, 1, 1);
6788                 GL_BlendFunc(GL_ONE, GL_ZERO);
6789
6790                 switch(vid.renderpath)
6791                 {
6792                 case RENDERPATH_GL20:
6793                 case RENDERPATH_GLES2:
6794                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6796                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6797                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6798                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6799                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6800                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6802                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6803                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6804                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6805                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6806                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6807                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6808                         break;
6809                 case RENDERPATH_D3D9:
6810 #ifdef SUPPORTD3D
6811                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6812                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6813                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6814                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6815                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6816                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6817                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6818                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6819                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6820                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6821                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6822                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6823                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6824                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6825                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6826 #endif
6827                         break;
6828                 case RENDERPATH_D3D10:
6829                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6830                         break;
6831                 case RENDERPATH_D3D11:
6832                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6833                         break;
6834                 case RENDERPATH_SOFT:
6835                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6836                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6837                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6838                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6839                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6840                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6841                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6842                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6843                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6844                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6845                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6846                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6847                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6848                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6849                         break;
6850                 default:
6851                         break;
6852                 }
6853                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6855                 break;
6856         case RENDERPATH_GL11:
6857         case RENDERPATH_GL13:
6858         case RENDERPATH_GLES1:
6859                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6860                 {
6861                         // apply a color tint to the whole view
6862                         R_ResetViewRendering2D(0, NULL, NULL);
6863                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865                         R_SetupShader_Generic_NoTexture(false, true);
6866                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6868                 }
6869                 break;
6870         }
6871 }
6872
6873 matrix4x4_t r_waterscrollmatrix;
6874
6875 void R_UpdateFog(void)
6876 {
6877         // Nehahra fog
6878         if (gamemode == GAME_NEHAHRA)
6879         {
6880                 if (gl_fogenable.integer)
6881                 {
6882                         r_refdef.oldgl_fogenable = true;
6883                         r_refdef.fog_density = gl_fogdensity.value;
6884                         r_refdef.fog_red = gl_fogred.value;
6885                         r_refdef.fog_green = gl_foggreen.value;
6886                         r_refdef.fog_blue = gl_fogblue.value;
6887                         r_refdef.fog_alpha = 1;
6888                         r_refdef.fog_start = 0;
6889                         r_refdef.fog_end = gl_skyclip.value;
6890                         r_refdef.fog_height = 1<<30;
6891                         r_refdef.fog_fadedepth = 128;
6892                 }
6893                 else if (r_refdef.oldgl_fogenable)
6894                 {
6895                         r_refdef.oldgl_fogenable = false;
6896                         r_refdef.fog_density = 0;
6897                         r_refdef.fog_red = 0;
6898                         r_refdef.fog_green = 0;
6899                         r_refdef.fog_blue = 0;
6900                         r_refdef.fog_alpha = 0;
6901                         r_refdef.fog_start = 0;
6902                         r_refdef.fog_end = 0;
6903                         r_refdef.fog_height = 1<<30;
6904                         r_refdef.fog_fadedepth = 128;
6905                 }
6906         }
6907
6908         // fog parms
6909         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6910         r_refdef.fog_start = max(0, r_refdef.fog_start);
6911         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6912
6913         if (r_refdef.fog_density && r_drawfog.integer)
6914         {
6915                 r_refdef.fogenabled = true;
6916                 // this is the point where the fog reaches 0.9986 alpha, which we
6917                 // consider a good enough cutoff point for the texture
6918                 // (0.9986 * 256 == 255.6)
6919                 if (r_fog_exp2.integer)
6920                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6921                 else
6922                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6923                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6924                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6925                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6926                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6927                         R_BuildFogHeightTexture();
6928                 // fog color was already set
6929                 // update the fog texture
6930                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6931                         R_BuildFogTexture();
6932                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6933                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6934         }
6935         else
6936                 r_refdef.fogenabled = false;
6937
6938         // fog color
6939         if (r_refdef.fog_density)
6940         {
6941                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6942                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6943                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6944
6945                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6946                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6947                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6948                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6949
6950                 {
6951                         vec3_t fogvec;
6952                         VectorCopy(r_refdef.fogcolor, fogvec);
6953                         //   color.rgb *= ContrastBoost * SceneBrightness;
6954                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6955                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6956                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6957                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6958                 }
6959         }
6960 }
6961
6962 void R_UpdateVariables(void)
6963 {
6964         R_Textures_Frame();
6965
6966         r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6967
6968         r_refdef.farclip = r_farclip_base.value;
6969         if (r_refdef.scene.worldmodel)
6970                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6971         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6972
6973         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6974                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6975         r_refdef.polygonfactor = 0;
6976         r_refdef.polygonoffset = 0;
6977         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6978         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6979
6980         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6981         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6982         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6983         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6984         r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6985         if (FAKELIGHT_ENABLED)
6986         {
6987                 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6988         }
6989         else if (r_refdef.scene.worldmodel)
6990         {
6991                 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6992         }
6993         if (r_showsurfaces.integer)
6994         {
6995                 r_refdef.scene.rtworld = false;
6996                 r_refdef.scene.rtworldshadows = false;
6997                 r_refdef.scene.rtdlight = false;
6998                 r_refdef.scene.rtdlightshadows = false;
6999                 r_refdef.scene.lightmapintensity = 0;
7000         }
7001
7002         r_gpuskeletal = false;
7003         switch(vid.renderpath)
7004         {
7005         case RENDERPATH_GL20:
7006                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7007         case RENDERPATH_D3D9:
7008         case RENDERPATH_D3D10:
7009         case RENDERPATH_D3D11:
7010         case RENDERPATH_SOFT:
7011         case RENDERPATH_GLES2:
7012                 if(!vid_gammatables_trivial)
7013                 {
7014                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7015                         {
7016                                 // build GLSL gamma texture
7017 #define RAMPWIDTH 256
7018                                 unsigned short ramp[RAMPWIDTH * 3];
7019                                 unsigned char rampbgr[RAMPWIDTH][4];
7020                                 int i;
7021
7022                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7023
7024                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7025                                 for(i = 0; i < RAMPWIDTH; ++i)
7026                                 {
7027                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7028                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7029                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7030                                         rampbgr[i][3] = 0;
7031                                 }
7032                                 if (r_texture_gammaramps)
7033                                 {
7034                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7035                                 }
7036                                 else
7037                                 {
7038                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7039                                 }
7040                         }
7041                 }
7042                 else
7043                 {
7044                         // remove GLSL gamma texture
7045                 }
7046                 break;
7047         case RENDERPATH_GL11:
7048         case RENDERPATH_GL13:
7049         case RENDERPATH_GLES1:
7050                 break;
7051         }
7052 }
7053
7054 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7055 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7056 /*
7057 ================
7058 R_SelectScene
7059 ================
7060 */
7061 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7062         if( scenetype != r_currentscenetype ) {
7063                 // store the old scenetype
7064                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7065                 r_currentscenetype = scenetype;
7066                 // move in the new scene
7067                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7068         }
7069 }
7070
7071 /*
7072 ================
7073 R_GetScenePointer
7074 ================
7075 */
7076 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7077 {
7078         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7079         if( scenetype == r_currentscenetype ) {
7080                 return &r_refdef.scene;
7081         } else {
7082                 return &r_scenes_store[ scenetype ];
7083         }
7084 }
7085
7086 static int R_SortEntities_Compare(const void *ap, const void *bp)
7087 {
7088         const entity_render_t *a = *(const entity_render_t **)ap;
7089         const entity_render_t *b = *(const entity_render_t **)bp;
7090
7091         // 1. compare model
7092         if(a->model < b->model)
7093                 return -1;
7094         if(a->model > b->model)
7095                 return +1;
7096
7097         // 2. compare skin
7098         // TODO possibly calculate the REAL skinnum here first using
7099         // skinscenes?
7100         if(a->skinnum < b->skinnum)
7101                 return -1;
7102         if(a->skinnum > b->skinnum)
7103                 return +1;
7104
7105         // everything we compared is equal
7106         return 0;
7107 }
7108 static void R_SortEntities(void)
7109 {
7110         // below or equal 2 ents, sorting never gains anything
7111         if(r_refdef.scene.numentities <= 2)
7112                 return;
7113         // sort
7114         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7115 }
7116
7117 /*
7118 ================
7119 R_RenderView
7120 ================
7121 */
7122 int dpsoftrast_test;
7123 extern cvar_t r_shadow_bouncegrid;
7124 void R_RenderView(void)
7125 {
7126         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7127         int fbo;
7128         rtexture_t *depthtexture;
7129         rtexture_t *colortexture;
7130
7131         dpsoftrast_test = r_test.integer;
7132
7133         if (r_timereport_active)
7134                 R_TimeReport("start");
7135         r_textureframe++; // used only by R_GetCurrentTexture
7136         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7137
7138         if(R_CompileShader_CheckStaticParms())
7139                 R_GLSL_Restart_f();
7140
7141         if (!r_drawentities.integer)
7142                 r_refdef.scene.numentities = 0;
7143         else if (r_sortentities.integer)
7144                 R_SortEntities();
7145
7146         R_AnimCache_ClearCache();
7147
7148         /* adjust for stereo display */
7149         if(R_Stereo_Active())
7150         {
7151                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
7152                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7153         }
7154
7155         if (r_refdef.view.isoverlay)
7156         {
7157                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7158                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7159                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7160                 R_TimeReport("depthclear");
7161
7162                 r_refdef.view.showdebug = false;
7163
7164                 r_fb.water.enabled = false;
7165                 r_fb.water.numwaterplanes = 0;
7166
7167                 R_RenderScene(0, NULL, NULL);
7168
7169                 r_refdef.view.matrix = originalmatrix;
7170
7171                 CHECKGLERROR
7172                 return;
7173         }
7174
7175         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7176         {
7177                 r_refdef.view.matrix = originalmatrix;
7178                 return;
7179         }
7180
7181         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7182
7183         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7184                 // in sRGB fallback, behave similar to true sRGB: convert this
7185                 // value from linear to sRGB
7186                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7187
7188         R_RenderView_UpdateViewVectors();
7189
7190         R_Shadow_UpdateWorldLightSelection();
7191
7192         R_Bloom_StartFrame();
7193
7194         // apply bloom brightness offset
7195         if(r_fb.bloomtexture[0])
7196                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7197
7198         R_Water_StartFrame();
7199
7200         // now we probably have an fbo to render into
7201         fbo = r_fb.fbo;
7202         depthtexture = r_fb.depthtexture;
7203         colortexture = r_fb.colortexture;
7204
7205         CHECKGLERROR
7206         if (r_timereport_active)
7207                 R_TimeReport("viewsetup");
7208
7209         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7210
7211         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7212         {
7213                 R_ClearScreen(r_refdef.fogenabled);
7214                 if (r_timereport_active)
7215                         R_TimeReport("viewclear");
7216         }
7217         r_refdef.view.clear = true;
7218
7219         r_refdef.view.showdebug = true;
7220
7221         R_View_Update();
7222         if (r_timereport_active)
7223                 R_TimeReport("visibility");
7224
7225         R_AnimCache_CacheVisibleEntities();
7226         if (r_timereport_active)
7227                 R_TimeReport("animcache");
7228
7229         R_Shadow_UpdateBounceGridTexture();
7230         if (r_timereport_active && r_shadow_bouncegrid.integer)
7231                 R_TimeReport("bouncegrid");
7232
7233         r_fb.water.numwaterplanes = 0;
7234         if (r_fb.water.enabled)
7235                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7236
7237         R_RenderScene(fbo, depthtexture, colortexture);
7238         r_fb.water.numwaterplanes = 0;
7239
7240         R_BlendView(fbo, depthtexture, colortexture);
7241         if (r_timereport_active)
7242                 R_TimeReport("blendview");
7243
7244         GL_Scissor(0, 0, vid.width, vid.height);
7245         GL_ScissorTest(false);
7246
7247         r_refdef.view.matrix = originalmatrix;
7248
7249         CHECKGLERROR
7250 }
7251
7252 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7253 {
7254         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7255         {
7256                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7257                 if (r_timereport_active)
7258                         R_TimeReport("waterworld");
7259         }
7260
7261         // don't let sound skip if going slow
7262         if (r_refdef.scene.extraupdate)
7263                 S_ExtraUpdate ();
7264
7265         R_DrawModelsAddWaterPlanes();
7266         if (r_timereport_active)
7267                 R_TimeReport("watermodels");
7268
7269         if (r_fb.water.numwaterplanes)
7270         {
7271                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7272                 if (r_timereport_active)
7273                         R_TimeReport("waterscenes");
7274         }
7275 }
7276
7277 extern cvar_t cl_locs_show;
7278 static void R_DrawLocs(void);
7279 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7280 static void R_DrawModelDecals(void);
7281 extern cvar_t cl_decals_newsystem;
7282 extern qboolean r_shadow_usingdeferredprepass;
7283 extern int r_shadow_shadowmapatlas_modelshadows_size;
7284 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7285 {
7286         qboolean shadowmapping = false;
7287
7288         if (r_timereport_active)
7289                 R_TimeReport("beginscene");
7290
7291         r_refdef.stats[r_stat_renders]++;
7292
7293         R_UpdateFog();
7294
7295         // don't let sound skip if going slow
7296         if (r_refdef.scene.extraupdate)
7297                 S_ExtraUpdate ();
7298
7299         R_MeshQueue_BeginScene();
7300
7301         R_SkyStartFrame();
7302
7303         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7304
7305         if (r_timereport_active)
7306                 R_TimeReport("skystartframe");
7307
7308         if (cl.csqc_vidvars.drawworld)
7309         {
7310                 // don't let sound skip if going slow
7311                 if (r_refdef.scene.extraupdate)
7312                         S_ExtraUpdate ();
7313
7314                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7315                 {
7316                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7317                         if (r_timereport_active)
7318                                 R_TimeReport("worldsky");
7319                 }
7320
7321                 if (R_DrawBrushModelsSky() && r_timereport_active)
7322                         R_TimeReport("bmodelsky");
7323
7324                 if (skyrendermasked && skyrenderlater)
7325                 {
7326                         // we have to force off the water clipping plane while rendering sky
7327                         R_SetupView(false, fbo, depthtexture, colortexture);
7328                         R_Sky();
7329                         R_SetupView(true, fbo, depthtexture, colortexture);
7330                         if (r_timereport_active)
7331                                 R_TimeReport("sky");
7332                 }
7333         }
7334
7335         R_Shadow_PrepareModelShadows();
7336         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7337         if (r_timereport_active)
7338                 R_TimeReport("preparelights");
7339
7340         // render all the shadowmaps that will be used for this view
7341         shadowmapping = R_Shadow_ShadowMappingEnabled();
7342         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7343         {
7344                 R_Shadow_DrawShadowMaps();
7345                 if (r_timereport_active)
7346                         R_TimeReport("shadowmaps");
7347         }
7348
7349         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7350         if (r_shadow_usingdeferredprepass)
7351                 R_Shadow_DrawPrepass();
7352
7353         // now we begin the forward pass of the view render
7354         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7355         {
7356                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7357                 if (r_timereport_active)
7358                         R_TimeReport("worlddepth");
7359         }
7360         if (r_depthfirst.integer >= 2)
7361         {
7362                 R_DrawModelsDepth();
7363                 if (r_timereport_active)
7364                         R_TimeReport("modeldepth");
7365         }
7366
7367         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7368         {
7369                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7370                 if (r_timereport_active)
7371                         R_TimeReport("world");
7372         }
7373
7374         // don't let sound skip if going slow
7375         if (r_refdef.scene.extraupdate)
7376                 S_ExtraUpdate ();
7377
7378         R_DrawModels();
7379         if (r_timereport_active)
7380                 R_TimeReport("models");
7381
7382         // don't let sound skip if going slow
7383         if (r_refdef.scene.extraupdate)
7384                 S_ExtraUpdate ();
7385
7386         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7387         {
7388                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7389                 R_Shadow_DrawModelShadows();
7390                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7391                 // don't let sound skip if going slow
7392                 if (r_refdef.scene.extraupdate)
7393                         S_ExtraUpdate ();
7394         }
7395
7396         if (!r_shadow_usingdeferredprepass)
7397         {
7398                 R_Shadow_DrawLights();
7399                 if (r_timereport_active)
7400                         R_TimeReport("rtlights");
7401         }
7402
7403         // don't let sound skip if going slow
7404         if (r_refdef.scene.extraupdate)
7405                 S_ExtraUpdate ();
7406
7407         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7408         {
7409                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410                 R_Shadow_DrawModelShadows();
7411                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412                 // don't let sound skip if going slow
7413                 if (r_refdef.scene.extraupdate)
7414                         S_ExtraUpdate ();
7415         }
7416
7417         if (cl.csqc_vidvars.drawworld)
7418         {
7419                 if (cl_decals_newsystem.integer)
7420                 {
7421                         R_DrawModelDecals();
7422                         if (r_timereport_active)
7423                                 R_TimeReport("modeldecals");
7424                 }
7425                 else
7426                 {
7427                         R_DrawDecals();
7428                         if (r_timereport_active)
7429                                 R_TimeReport("decals");
7430                 }
7431
7432                 R_DrawParticles();
7433                 if (r_timereport_active)
7434                         R_TimeReport("particles");
7435
7436                 R_DrawExplosions();
7437                 if (r_timereport_active)
7438                         R_TimeReport("explosions");
7439         }
7440
7441         if (cl.csqc_loaded)
7442                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7443
7444         if (r_refdef.view.showdebug)
7445         {
7446                 if (cl_locs_show.integer)
7447                 {
7448                         R_DrawLocs();
7449                         if (r_timereport_active)
7450                                 R_TimeReport("showlocs");
7451                 }
7452
7453                 if (r_drawportals.integer)
7454                 {
7455                         R_DrawPortals();
7456                         if (r_timereport_active)
7457                                 R_TimeReport("portals");
7458                 }
7459
7460                 if (r_showbboxes_client.value > 0)
7461                 {
7462                         R_DrawEntityBBoxes(CLVM_prog);
7463                         if (r_timereport_active)
7464                                 R_TimeReport("clbboxes");
7465                 }
7466                 if (r_showbboxes.value > 0)
7467                 {
7468                         R_DrawEntityBBoxes(SVVM_prog);
7469                         if (r_timereport_active)
7470                                 R_TimeReport("svbboxes");
7471                 }
7472         }
7473
7474         if (r_transparent.integer)
7475         {
7476                 R_MeshQueue_RenderTransparent();
7477                 if (r_timereport_active)
7478                         R_TimeReport("drawtrans");
7479         }
7480
7481         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7482         {
7483                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7484                 if (r_timereport_active)
7485                         R_TimeReport("worlddebug");
7486                 R_DrawModelsDebug();
7487                 if (r_timereport_active)
7488                         R_TimeReport("modeldebug");
7489         }
7490
7491         if (cl.csqc_vidvars.drawworld)
7492         {
7493                 R_Shadow_DrawCoronas();
7494                 if (r_timereport_active)
7495                         R_TimeReport("coronas");
7496         }
7497
7498 #if 0
7499         {
7500                 GL_DepthTest(false);
7501                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7502                 GL_Color(1, 1, 1, 1);
7503                 qglBegin(GL_POLYGON);
7504                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7505                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7506                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7507                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7508                 qglEnd();
7509                 qglBegin(GL_POLYGON);
7510                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7511                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7512                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7513                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7514                 qglEnd();
7515                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7516         }
7517 #endif
7518
7519         // don't let sound skip if going slow
7520         if (r_refdef.scene.extraupdate)
7521                 S_ExtraUpdate ();
7522 }
7523
7524 static const unsigned short bboxelements[36] =
7525 {
7526         5, 1, 3, 5, 3, 7,
7527         6, 2, 0, 6, 0, 4,
7528         7, 3, 2, 7, 2, 6,
7529         4, 0, 1, 4, 1, 5,
7530         4, 5, 7, 4, 7, 6,
7531         1, 0, 2, 1, 2, 3,
7532 };
7533
7534 #define BBOXEDGES 13
7535 static const float bboxedges[BBOXEDGES][6] = 
7536 {
7537         // whole box
7538         { 0, 0, 0, 1, 1, 1 },
7539         // bottom edges
7540         { 0, 0, 0, 0, 1, 0 },
7541         { 0, 0, 0, 1, 0, 0 },
7542         { 0, 1, 0, 1, 1, 0 },
7543         { 1, 0, 0, 1, 1, 0 },
7544         // top edges
7545         { 0, 0, 1, 0, 1, 1 },
7546         { 0, 0, 1, 1, 0, 1 },
7547         { 0, 1, 1, 1, 1, 1 },
7548         { 1, 0, 1, 1, 1, 1 },
7549         // vertical edges
7550         { 0, 0, 0, 0, 0, 1 },
7551         { 1, 0, 0, 1, 0, 1 },
7552         { 0, 1, 0, 0, 1, 1 },
7553         { 1, 1, 0, 1, 1, 1 },
7554 };
7555
7556 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7557 {
7558         int numvertices = BBOXEDGES * 8;
7559         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7560         int numtriangles = BBOXEDGES * 12;
7561         unsigned short elements[BBOXEDGES * 36];
7562         int i, edge;
7563         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7564
7565         RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7566
7567         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7568         GL_DepthMask(false);
7569         GL_DepthRange(0, 1);
7570         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7571
7572         for (edge = 0; edge < BBOXEDGES; edge++)
7573         {
7574                 for (i = 0; i < 3; i++)
7575                 {
7576                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7577                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7578                 }
7579                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7580                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7581                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7582                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7583                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7584                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7585                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7586                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7587                 for (i = 0; i < 36; i++)
7588                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7589         }
7590         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7591         if (r_refdef.fogenabled)
7592         {
7593                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7594                 {
7595                         f1 = RSurf_FogVertex(v);
7596                         f2 = 1 - f1;
7597                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7598                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7599                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7600                 }
7601         }
7602         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7603         R_Mesh_ResetTextureState();
7604         R_SetupShader_Generic_NoTexture(false, false);
7605         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7606 }
7607
7608 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7609 {
7610         // hacky overloading of the parameters
7611         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7612         int i;
7613         float color[4];
7614         prvm_edict_t *edict;
7615
7616         GL_CullFace(GL_NONE);
7617         R_SetupShader_Generic_NoTexture(false, false);
7618
7619         for (i = 0;i < numsurfaces;i++)
7620         {
7621                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7622                 switch ((int)PRVM_serveredictfloat(edict, solid))
7623                 {
7624                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7625                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7626                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7627                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7628                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7629                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7630                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7631                 }
7632                 if (prog == CLVM_prog)
7633                         color[3] *= r_showbboxes_client.value;
7634                 else
7635                         color[3] *= r_showbboxes.value;
7636                 color[3] = bound(0, color[3], 1);
7637                 GL_DepthTest(!r_showdisabledepthtest.integer);
7638                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7639         }
7640 }
7641
7642 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7643 {
7644         int i;
7645         prvm_edict_t *edict;
7646         vec3_t center;
7647
7648         if (prog == NULL)
7649                 return;
7650
7651         for (i = 0; i < prog->num_edicts; i++)
7652         {
7653                 edict = PRVM_EDICT_NUM(i);
7654                 if (edict->priv.server->free)
7655                         continue;
7656                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7657                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7658                         continue;
7659                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7660                         continue;
7661                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7662                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7663         }
7664 }
7665
7666 static const int nomodelelement3i[24] =
7667 {
7668         5, 2, 0,
7669         5, 1, 2,
7670         5, 0, 3,
7671         5, 3, 1,
7672         0, 2, 4,
7673         2, 1, 4,
7674         3, 0, 4,
7675         1, 3, 4
7676 };
7677
7678 static const unsigned short nomodelelement3s[24] =
7679 {
7680         5, 2, 0,
7681         5, 1, 2,
7682         5, 0, 3,
7683         5, 3, 1,
7684         0, 2, 4,
7685         2, 1, 4,
7686         3, 0, 4,
7687         1, 3, 4
7688 };
7689
7690 static const float nomodelvertex3f[6*3] =
7691 {
7692         -16,   0,   0,
7693          16,   0,   0,
7694           0, -16,   0,
7695           0,  16,   0,
7696           0,   0, -16,
7697           0,   0,  16
7698 };
7699
7700 static const float nomodelcolor4f[6*4] =
7701 {
7702         0.0f, 0.0f, 0.5f, 1.0f,
7703         0.0f, 0.0f, 0.5f, 1.0f,
7704         0.0f, 0.5f, 0.0f, 1.0f,
7705         0.0f, 0.5f, 0.0f, 1.0f,
7706         0.5f, 0.0f, 0.0f, 1.0f,
7707         0.5f, 0.0f, 0.0f, 1.0f
7708 };
7709
7710 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7711 {
7712         int i;
7713         float f1, f2, *c;
7714         float color4f[6*4];
7715
7716         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7717
7718         // this is only called once per entity so numsurfaces is always 1, and
7719         // surfacelist is always {0}, so this code does not handle batches
7720
7721         if (rsurface.ent_flags & RENDER_ADDITIVE)
7722         {
7723                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7724                 GL_DepthMask(false);
7725         }
7726         else if (ent->alpha < 1)
7727         {
7728                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7729                 GL_DepthMask(false);
7730         }
7731         else
7732         {
7733                 GL_BlendFunc(GL_ONE, GL_ZERO);
7734                 GL_DepthMask(true);
7735         }
7736         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7737         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7738         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7739         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7740         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7741         for (i = 0, c = color4f;i < 6;i++, c += 4)
7742         {
7743                 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7744                 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7745                 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7746                 c[3] *= ent->alpha;
7747         }
7748         if (r_refdef.fogenabled)
7749         {
7750                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7751                 {
7752                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7753                         f2 = 1 - f1;
7754                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7755                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7756                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7757                 }
7758         }
7759 //      R_Mesh_ResetTextureState();
7760         R_SetupShader_Generic_NoTexture(false, false);
7761         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7762         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7763 }
7764
7765 void R_DrawNoModel(entity_render_t *ent)
7766 {
7767         vec3_t org;
7768         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7769         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7770                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7771         else
7772                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7773 }
7774
7775 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7776 {
7777         vec3_t right1, right2, diff, normal;
7778
7779         VectorSubtract (org2, org1, normal);
7780
7781         // calculate 'right' vector for start
7782         VectorSubtract (r_refdef.view.origin, org1, diff);
7783         CrossProduct (normal, diff, right1);
7784         VectorNormalize (right1);
7785
7786         // calculate 'right' vector for end
7787         VectorSubtract (r_refdef.view.origin, org2, diff);
7788         CrossProduct (normal, diff, right2);
7789         VectorNormalize (right2);
7790
7791         vert[ 0] = org1[0] + width * right1[0];
7792         vert[ 1] = org1[1] + width * right1[1];
7793         vert[ 2] = org1[2] + width * right1[2];
7794         vert[ 3] = org1[0] - width * right1[0];
7795         vert[ 4] = org1[1] - width * right1[1];
7796         vert[ 5] = org1[2] - width * right1[2];
7797         vert[ 6] = org2[0] - width * right2[0];
7798         vert[ 7] = org2[1] - width * right2[1];
7799         vert[ 8] = org2[2] - width * right2[2];
7800         vert[ 9] = org2[0] + width * right2[0];
7801         vert[10] = org2[1] + width * right2[1];
7802         vert[11] = org2[2] + width * right2[2];
7803 }
7804
7805 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7806 {
7807         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7808         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7809         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7810         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7811         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7812         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7813         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7814         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7815         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7816         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7817         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7818         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7819 }
7820
7821 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7822 {
7823         int i;
7824         float *vertex3f;
7825         float v[3];
7826         VectorSet(v, x, y, z);
7827         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7828                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7829                         break;
7830         if (i == mesh->numvertices)
7831         {
7832                 if (mesh->numvertices < mesh->maxvertices)
7833                 {
7834                         VectorCopy(v, vertex3f);
7835                         mesh->numvertices++;
7836                 }
7837                 return mesh->numvertices;
7838         }
7839         else
7840                 return i;
7841 }
7842
7843 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7844 {
7845         int i;
7846         int *e, element[3];
7847         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7848         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7849         e = mesh->element3i + mesh->numtriangles * 3;
7850         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7851         {
7852                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7853                 if (mesh->numtriangles < mesh->maxtriangles)
7854                 {
7855                         *e++ = element[0];
7856                         *e++ = element[1];
7857                         *e++ = element[2];
7858                         mesh->numtriangles++;
7859                 }
7860                 element[1] = element[2];
7861         }
7862 }
7863
7864 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7865 {
7866         int i;
7867         int *e, element[3];
7868         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7869         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7870         e = mesh->element3i + mesh->numtriangles * 3;
7871         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7872         {
7873                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7874                 if (mesh->numtriangles < mesh->maxtriangles)
7875                 {
7876                         *e++ = element[0];
7877                         *e++ = element[1];
7878                         *e++ = element[2];
7879                         mesh->numtriangles++;
7880                 }
7881                 element[1] = element[2];
7882         }
7883 }
7884
7885 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7886 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7887 {
7888         int planenum, planenum2;
7889         int w;
7890         int tempnumpoints;
7891         mplane_t *plane, *plane2;
7892         double maxdist;
7893         double temppoints[2][256*3];
7894         // figure out how large a bounding box we need to properly compute this brush
7895         maxdist = 0;
7896         for (w = 0;w < numplanes;w++)
7897                 maxdist = max(maxdist, fabs(planes[w].dist));
7898         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7899         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7900         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7901         {
7902                 w = 0;
7903                 tempnumpoints = 4;
7904                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7905                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7906                 {
7907                         if (planenum2 == planenum)
7908                                 continue;
7909                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7910                         w = !w;
7911                 }
7912                 if (tempnumpoints < 3)
7913                         continue;
7914                 // generate elements forming a triangle fan for this polygon
7915                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7916         }
7917 }
7918
7919 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7920 {
7921         texturelayer_t *layer;
7922         layer = t->currentlayers + t->currentnumlayers++;
7923         layer->type = type;
7924         layer->depthmask = depthmask;
7925         layer->blendfunc1 = blendfunc1;
7926         layer->blendfunc2 = blendfunc2;
7927         layer->texture = texture;
7928         layer->texmatrix = *matrix;
7929         layer->color[0] = r;
7930         layer->color[1] = g;
7931         layer->color[2] = b;
7932         layer->color[3] = a;
7933 }
7934
7935 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7936 {
7937         if(parms[0] == 0 && parms[1] == 0)
7938                 return false;
7939         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7940                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7941                         return false;
7942         return true;
7943 }
7944
7945 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7946 {
7947         double index, f;
7948         index = parms[2] + rsurface.shadertime * parms[3];
7949         index -= floor(index);
7950         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7951         {
7952         default:
7953         case Q3WAVEFUNC_NONE:
7954         case Q3WAVEFUNC_NOISE:
7955         case Q3WAVEFUNC_COUNT:
7956                 f = 0;
7957                 break;
7958         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7959         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7960         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7961         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7962         case Q3WAVEFUNC_TRIANGLE:
7963                 index *= 4;
7964                 f = index - floor(index);
7965                 if (index < 1)
7966                 {
7967                         // f = f;
7968                 }
7969                 else if (index < 2)
7970                         f = 1 - f;
7971                 else if (index < 3)
7972                         f = -f;
7973                 else
7974                         f = -(1 - f);
7975                 break;
7976         }
7977         f = parms[0] + parms[1] * f;
7978         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7979                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7980         return (float) f;
7981 }
7982
7983 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7984 {
7985         int w, h, idx;
7986         float shadertime;
7987         float f;
7988         float offsetd[2];
7989         float tcmat[12];
7990         matrix4x4_t matrix, temp;
7991         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7992         // it's better to have one huge fixup every 9 hours than gradual
7993         // degradation over time which looks consistently bad after many hours.
7994         //
7995         // tcmod scroll in particular suffers from this degradation which can't be
7996         // effectively worked around even with floor() tricks because we don't
7997         // know if tcmod scroll is the last tcmod being applied, and for clampmap
7998         // a workaround involving floor() would be incorrect anyway...
7999         shadertime = rsurface.shadertime;
8000         if (shadertime >= 32768.0f)
8001                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8002         switch(tcmod->tcmod)
8003         {
8004                 case Q3TCMOD_COUNT:
8005                 case Q3TCMOD_NONE:
8006                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8007                                 matrix = r_waterscrollmatrix;
8008                         else
8009                                 matrix = identitymatrix;
8010                         break;
8011                 case Q3TCMOD_ENTITYTRANSLATE:
8012                         // this is used in Q3 to allow the gamecode to control texcoord
8013                         // scrolling on the entity, which is not supported in darkplaces yet.
8014                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8015                         break;
8016                 case Q3TCMOD_ROTATE:
8017                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8018                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8019                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8020                         break;
8021                 case Q3TCMOD_SCALE:
8022                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8023                         break;
8024                 case Q3TCMOD_SCROLL:
8025                         // this particular tcmod is a "bug for bug" compatible one with regards to
8026                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8027                         // specifically did the wrapping and so we must mimic that...
8028                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8029                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8030                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8031                         break;
8032                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8033                         w = (int) tcmod->parms[0];
8034                         h = (int) tcmod->parms[1];
8035                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8036                         f = f - floor(f);
8037                         idx = (int) floor(f * w * h);
8038                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8039                         break;
8040                 case Q3TCMOD_STRETCH:
8041                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8042                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8043                         break;
8044                 case Q3TCMOD_TRANSFORM:
8045                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8046                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8047                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8048                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8049                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8050                         break;
8051                 case Q3TCMOD_TURBULENT:
8052                         // this is handled in the RSurf_PrepareVertices function
8053                         matrix = identitymatrix;
8054                         break;
8055         }
8056         temp = *texmatrix;
8057         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8058 }
8059
8060 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8061 {
8062         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8063         char name[MAX_QPATH];
8064         skinframe_t *skinframe;
8065         unsigned char pixels[296*194];
8066         strlcpy(cache->name, skinname, sizeof(cache->name));
8067         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8068         if (developer_loading.integer)
8069                 Con_Printf("loading %s\n", name);
8070         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8071         if (!skinframe || !skinframe->base)
8072         {
8073                 unsigned char *f;
8074                 fs_offset_t filesize;
8075                 skinframe = NULL;
8076                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8077                 if (f)
8078                 {
8079                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8080                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8081                         Mem_Free(f);
8082                 }
8083         }
8084         cache->skinframe = skinframe;
8085 }
8086
8087 texture_t *R_GetCurrentTexture(texture_t *t)
8088 {
8089         int i, q;
8090         const entity_render_t *ent = rsurface.entity;
8091         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8092         q3shaderinfo_layer_tcmod_t *tcmod;
8093         float specularscale = 0.0f;
8094
8095         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8096                 return t->currentframe;
8097         t->update_lastrenderframe = r_textureframe;
8098         t->update_lastrenderentity = (void *)ent;
8099
8100         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8101                 t->camera_entity = ent->entitynumber;
8102         else
8103                 t->camera_entity = 0;
8104
8105         // switch to an alternate material if this is a q1bsp animated material
8106         {
8107                 texture_t *texture = t;
8108                 int s = rsurface.ent_skinnum;
8109                 if ((unsigned int)s >= (unsigned int)model->numskins)
8110                         s = 0;
8111                 if (model->skinscenes)
8112                 {
8113                         if (model->skinscenes[s].framecount > 1)
8114                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8115                         else
8116                                 s = model->skinscenes[s].firstframe;
8117                 }
8118                 if (s > 0)
8119                         t = t + s * model->num_surfaces;
8120                 if (t->animated)
8121                 {
8122                         // use an alternate animation if the entity's frame is not 0,
8123                         // and only if the texture has an alternate animation
8124                         if (t->animated == 2) // q2bsp
8125                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8126                         else if (rsurface.ent_alttextures && t->anim_total[1])
8127                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8128                         else
8129                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8130                 }
8131                 texture->currentframe = t;
8132         }
8133
8134         // update currentskinframe to be a qw skin or animation frame
8135         if (rsurface.ent_qwskin >= 0)
8136         {
8137                 i = rsurface.ent_qwskin;
8138                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8139                 {
8140                         r_qwskincache_size = cl.maxclients;
8141                         if (r_qwskincache)
8142                                 Mem_Free(r_qwskincache);
8143                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8144                 }
8145                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8146                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8147                 t->currentskinframe = r_qwskincache[i].skinframe;
8148                 if (t->materialshaderpass && t->currentskinframe == NULL)
8149                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8150         }
8151         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8152                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8153         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8154                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8155
8156         t->currentmaterialflags = t->basematerialflags;
8157         t->currentalpha = rsurface.entity->alpha * t->basealpha;
8158         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8159                 t->currentalpha *= r_wateralpha.value;
8160         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8161                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8162         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8163                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8164
8165         // decide on which type of lighting to use for this surface
8166         if (rsurface.entity->render_modellight_forced)
8167                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8168         if (rsurface.entity->render_rtlight_disabled)
8169                 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8170         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8171         {
8172                 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8173                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8174                 for (q = 0; q < 3; q++)
8175                 {
8176                         t->render_glowmod[q] = rsurface.entity->glowmod[q];
8177                         t->render_modellight_lightdir[q] = q == 2;
8178                         t->render_modellight_ambient[q] = 1;
8179                         t->render_modellight_diffuse[q] = 0;
8180                         t->render_modellight_specular[q] = 0;
8181                         t->render_lightmap_ambient[q] = 0;
8182                         t->render_lightmap_diffuse[q] = 0;
8183                         t->render_lightmap_specular[q] = 0;
8184                         t->render_rtlight_diffuse[q] = 0;
8185                         t->render_rtlight_specular[q] = 0;
8186                 }
8187         }
8188         else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8189         {
8190                 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8191                 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8192                 for (q = 0; q < 3; q++)
8193                 {
8194                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8195                         t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8196                         t->render_modellight_lightdir[q] = q == 2;
8197                         t->render_modellight_diffuse[q] = 0;
8198                         t->render_modellight_specular[q] = 0;
8199                         t->render_lightmap_ambient[q] = 0;
8200                         t->render_lightmap_diffuse[q] = 0;
8201                         t->render_lightmap_specular[q] = 0;
8202                         t->render_rtlight_diffuse[q] = 0;
8203                         t->render_rtlight_specular[q] = 0;
8204                 }
8205         }
8206         else if (FAKELIGHT_ENABLED)
8207         {
8208                 // no modellight if using fakelight for the map
8209                 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8210                 for (q = 0; q < 3; q++)
8211                 {
8212                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8213                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8214                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8215                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8216                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8217                         t->render_lightmap_ambient[q] = 0;
8218                         t->render_lightmap_diffuse[q] = 0;
8219                         t->render_lightmap_specular[q] = 0;
8220                         t->render_rtlight_diffuse[q] = 0;
8221                         t->render_rtlight_specular[q] = 0;
8222                 }
8223         }
8224         else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8225         {
8226                 // ambient + single direction light (modellight)
8227                 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8228                 for (q = 0; q < 3; q++)
8229                 {
8230                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8231                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8232                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8233                         t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8234                         t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8235                         t->render_lightmap_ambient[q] = 0;
8236                         t->render_lightmap_diffuse[q] = 0;
8237                         t->render_lightmap_specular[q] = 0;
8238                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8239                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8240                 }
8241         }
8242         else
8243         {
8244                 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8245                 for (q = 0; q < 3; q++)
8246                 {
8247                         t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8248                         t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8249                         t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8250                         t->render_modellight_diffuse[q] = 0;
8251                         t->render_modellight_specular[q] = 0;
8252                         t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8253                         t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8254                         t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8255                         t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8256                         t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8257                 }
8258         }
8259
8260         for (q = 0; q < 3; q++)
8261         {
8262                 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8263                 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8264         }
8265
8266         if (rsurface.ent_flags & RENDER_ADDITIVE)
8267                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8268         else if (t->currentalpha < 1)
8269                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8270         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8271         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8272                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8273         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8274                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8275         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8276                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8277         if (t->backgroundshaderpass)
8278                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8279         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8280         {
8281                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8282                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8283         }
8284         else
8285                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8286         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8287         {
8288                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8289                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8290         }
8291         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8292                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8293
8294         // there is no tcmod
8295         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8296         {
8297                 t->currenttexmatrix = r_waterscrollmatrix;
8298                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8299         }
8300         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8301         {
8302                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8303                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8304         }
8305
8306         if (t->materialshaderpass)
8307                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8308                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8309
8310         t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8311         if (t->currentskinframe->qpixels)
8312                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8313         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8314         if (!t->basetexture)
8315                 t->basetexture = r_texture_notexture;
8316         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8317         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8318         t->nmaptexture = t->currentskinframe->nmap;
8319         if (!t->nmaptexture)
8320                 t->nmaptexture = r_texture_blanknormalmap;
8321         t->glosstexture = r_texture_black;
8322         t->glowtexture = t->currentskinframe->glow;
8323         t->fogtexture = t->currentskinframe->fog;
8324         t->reflectmasktexture = t->currentskinframe->reflect;
8325         if (t->backgroundshaderpass)
8326         {
8327                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8328                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8329                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8330                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8331                 t->backgroundglosstexture = r_texture_black;
8332                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8333                 if (!t->backgroundnmaptexture)
8334                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8335                 // make sure that if glow is going to be used, both textures are not NULL
8336                 if (!t->backgroundglowtexture && t->glowtexture)
8337                         t->backgroundglowtexture = r_texture_black;
8338                 if (!t->glowtexture && t->backgroundglowtexture)
8339                         t->glowtexture = r_texture_black;
8340         }
8341         else
8342         {
8343                 t->backgroundbasetexture = r_texture_white;
8344                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8345                 t->backgroundglosstexture = r_texture_black;
8346                 t->backgroundglowtexture = NULL;
8347         }
8348         t->specularpower = r_shadow_glossexponent.value;
8349         // TODO: store reference values for these in the texture?
8350         if (r_shadow_gloss.integer > 0)
8351         {
8352                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8353                 {
8354                         if (r_shadow_glossintensity.value > 0)
8355                         {
8356                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8357                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8358                                 specularscale = r_shadow_glossintensity.value;
8359                         }
8360                 }
8361                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8362                 {
8363                         t->glosstexture = r_texture_white;
8364                         t->backgroundglosstexture = r_texture_white;
8365                         specularscale = r_shadow_gloss2intensity.value;
8366                         t->specularpower = r_shadow_gloss2exponent.value;
8367                 }
8368         }
8369         specularscale *= t->specularscalemod;
8370         t->specularpower *= t->specularpowermod;
8371
8372         // lightmaps mode looks bad with dlights using actual texturing, so turn
8373         // off the colormap and glossmap, but leave the normalmap on as it still
8374         // accurately represents the shading involved
8375         if (gl_lightmaps.integer)
8376         {
8377                 t->basetexture = r_texture_grey128;
8378                 t->pantstexture = r_texture_black;
8379                 t->shirttexture = r_texture_black;
8380                 if (gl_lightmaps.integer < 2)
8381                         t->nmaptexture = r_texture_blanknormalmap;
8382                 t->glosstexture = r_texture_black;
8383                 t->glowtexture = NULL;
8384                 t->fogtexture = NULL;
8385                 t->reflectmasktexture = NULL;
8386                 t->backgroundbasetexture = NULL;
8387                 if (gl_lightmaps.integer < 2)
8388                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8389                 t->backgroundglosstexture = r_texture_black;
8390                 t->backgroundglowtexture = NULL;
8391                 specularscale = 0;
8392                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8393         }
8394
8395         if (specularscale != 1.0f)
8396         {
8397                 for (q = 0; q < 3; q++)
8398                 {
8399                         t->render_modellight_specular[q] *= specularscale;
8400                         t->render_lightmap_specular[q] *= specularscale;
8401                         t->render_rtlight_specular[q] *= specularscale;
8402                 }
8403         }
8404
8405         t->currentnumlayers = 0;
8406         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8407         {
8408                 int blendfunc1, blendfunc2;
8409                 qboolean depthmask;
8410                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8411                 {
8412                         blendfunc1 = GL_SRC_ALPHA;
8413                         blendfunc2 = GL_ONE;
8414                 }
8415                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8416                 {
8417                         blendfunc1 = GL_SRC_ALPHA;
8418                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8419                 }
8420                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8421                 {
8422                         blendfunc1 = t->customblendfunc[0];
8423                         blendfunc2 = t->customblendfunc[1];
8424                 }
8425                 else
8426                 {
8427                         blendfunc1 = GL_ONE;
8428                         blendfunc2 = GL_ZERO;
8429                 }
8430                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8431                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8432                 {
8433                         // basic lit geometry
8434                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8435                         // add pants/shirt if needed
8436                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8437                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8438                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8439                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8440                 }
8441                 else
8442                 {
8443                         // basic lit geometry
8444                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8445                         // add pants/shirt if needed
8446                         if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8447                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2]  * t->render_lightmap_diffuse[2], t->currentalpha);
8448                         if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8449                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8450                         // now add ambient passes if needed
8451                         if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8452                         {
8453                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8454                                 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8455                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8456                                 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8457                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8458                         }
8459                 }
8460                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8461                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8462                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8463                 {
8464                         // if this is opaque use alpha blend which will darken the earlier
8465                         // passes cheaply.
8466                         //
8467                         // if this is an alpha blended material, all the earlier passes
8468                         // were darkened by fog already, so we only need to add the fog
8469                         // color ontop through the fog mask texture
8470                         //
8471                         // if this is an additive blended material, all the earlier passes
8472                         // were darkened by fog already, and we should not add fog color
8473                         // (because the background was not darkened, there is no fog color
8474                         // that was lost behind it).
8475                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8476                 }
8477         }
8478
8479         return t;
8480 }
8481
8482 rsurfacestate_t rsurface;
8483
8484 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8485 {
8486         dp_model_t *model = ent->model;
8487         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8488         //      return;
8489         rsurface.entity = (entity_render_t *)ent;
8490         rsurface.skeleton = ent->skeleton;
8491         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8492         rsurface.ent_skinnum = ent->skinnum;
8493         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8494         rsurface.ent_flags = ent->flags;
8495         if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8496                 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8497         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8498         rsurface.matrix = ent->matrix;
8499         rsurface.inversematrix = ent->inversematrix;
8500         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8501         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8502         R_EntityMatrix(&rsurface.matrix);
8503         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8504         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8505         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8506         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8507         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8508         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8509         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8510         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8511         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8512         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8513         if (ent->model->brush.submodel && !prepass)
8514         {
8515                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8516                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8517         }
8518         // if the animcache code decided it should use the shader path, skip the deform step
8519         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8520         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8521         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8522         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8523         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8524         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8525         {
8526                 if (ent->animcache_vertex3f)
8527                 {
8528                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8529                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8530                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8531                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8532                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8533                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8534                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8535                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8536                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8537                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8538                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8539                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8540                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8541                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8542                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8543                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8544                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8545                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8546                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8547                 }
8548                 else if (wanttangents)
8549                 {
8550                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8551                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8552                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8553                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8554                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8555                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8556                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8557                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8558                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8559                         rsurface.modelvertexmesh = NULL;
8560                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8561                         rsurface.modelvertexmesh_bufferoffset = 0;
8562                         rsurface.modelvertex3f_vertexbuffer = NULL;
8563                         rsurface.modelvertex3f_bufferoffset = 0;
8564                         rsurface.modelvertex3f_vertexbuffer = 0;
8565                         rsurface.modelvertex3f_bufferoffset = 0;
8566                         rsurface.modelsvector3f_vertexbuffer = 0;
8567                         rsurface.modelsvector3f_bufferoffset = 0;
8568                         rsurface.modeltvector3f_vertexbuffer = 0;
8569                         rsurface.modeltvector3f_bufferoffset = 0;
8570                         rsurface.modelnormal3f_vertexbuffer = 0;
8571                         rsurface.modelnormal3f_bufferoffset = 0;
8572                 }
8573                 else if (wantnormals)
8574                 {
8575                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8576                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8577                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8578                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8579                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8580                         rsurface.modelsvector3f = NULL;
8581                         rsurface.modeltvector3f = NULL;
8582                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8583                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8584                         rsurface.modelvertexmesh = NULL;
8585                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8586                         rsurface.modelvertexmesh_bufferoffset = 0;
8587                         rsurface.modelvertex3f_vertexbuffer = NULL;
8588                         rsurface.modelvertex3f_bufferoffset = 0;
8589                         rsurface.modelvertex3f_vertexbuffer = 0;
8590                         rsurface.modelvertex3f_bufferoffset = 0;
8591                         rsurface.modelsvector3f_vertexbuffer = 0;
8592                         rsurface.modelsvector3f_bufferoffset = 0;
8593                         rsurface.modeltvector3f_vertexbuffer = 0;
8594                         rsurface.modeltvector3f_bufferoffset = 0;
8595                         rsurface.modelnormal3f_vertexbuffer = 0;
8596                         rsurface.modelnormal3f_bufferoffset = 0;
8597                 }
8598                 else
8599                 {
8600                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8601                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8602                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8603                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8604                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8605                         rsurface.modelsvector3f = NULL;
8606                         rsurface.modeltvector3f = NULL;
8607                         rsurface.modelnormal3f = NULL;
8608                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8609                         rsurface.modelvertexmesh = NULL;
8610                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8611                         rsurface.modelvertexmesh_bufferoffset = 0;
8612                         rsurface.modelvertex3f_vertexbuffer = NULL;
8613                         rsurface.modelvertex3f_bufferoffset = 0;
8614                         rsurface.modelvertex3f_vertexbuffer = 0;
8615                         rsurface.modelvertex3f_bufferoffset = 0;
8616                         rsurface.modelsvector3f_vertexbuffer = 0;
8617                         rsurface.modelsvector3f_bufferoffset = 0;
8618                         rsurface.modeltvector3f_vertexbuffer = 0;
8619                         rsurface.modeltvector3f_bufferoffset = 0;
8620                         rsurface.modelnormal3f_vertexbuffer = 0;
8621                         rsurface.modelnormal3f_bufferoffset = 0;
8622                 }
8623                 rsurface.modelgeneratedvertex = true;
8624         }
8625         else
8626         {
8627                 if (rsurface.entityskeletaltransform3x4)
8628                 {
8629                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8630                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8631                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8632                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8633                 }
8634                 else
8635                 {
8636                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8637                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8638                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8639                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8640                 }
8641                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8642                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8644                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8645                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8647                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8648                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8649                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8650                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8651                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8652                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8653                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8654                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8655                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8656                 rsurface.modelgeneratedvertex = false;
8657         }
8658         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8659         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8660         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8661         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8662         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8663         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8664         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8665         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8666         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8667         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8668         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8669         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8670         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8671         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8672         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8673         rsurface.modelelement3i = model->surfmesh.data_element3i;
8674         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8675         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8676         rsurface.modelelement3s = model->surfmesh.data_element3s;
8677         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8678         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8679         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8680         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8681         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8682         rsurface.modelsurfaces = model->data_surfaces;
8683         rsurface.batchgeneratedvertex = false;
8684         rsurface.batchfirstvertex = 0;
8685         rsurface.batchnumvertices = 0;
8686         rsurface.batchfirsttriangle = 0;
8687         rsurface.batchnumtriangles = 0;
8688         rsurface.batchvertex3f  = NULL;
8689         rsurface.batchvertex3f_vertexbuffer = NULL;
8690         rsurface.batchvertex3f_bufferoffset = 0;
8691         rsurface.batchsvector3f = NULL;
8692         rsurface.batchsvector3f_vertexbuffer = NULL;
8693         rsurface.batchsvector3f_bufferoffset = 0;
8694         rsurface.batchtvector3f = NULL;
8695         rsurface.batchtvector3f_vertexbuffer = NULL;
8696         rsurface.batchtvector3f_bufferoffset = 0;
8697         rsurface.batchnormal3f  = NULL;
8698         rsurface.batchnormal3f_vertexbuffer = NULL;
8699         rsurface.batchnormal3f_bufferoffset = 0;
8700         rsurface.batchlightmapcolor4f = NULL;
8701         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8702         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8703         rsurface.batchtexcoordtexture2f = NULL;
8704         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8705         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8706         rsurface.batchtexcoordlightmap2f = NULL;
8707         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8708         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8709         rsurface.batchskeletalindex4ub = NULL;
8710         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8711         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8712         rsurface.batchskeletalweight4ub = NULL;
8713         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8714         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8715         rsurface.batchvertexmesh = NULL;
8716         rsurface.batchvertexmesh_vertexbuffer = NULL;
8717         rsurface.batchvertexmesh_bufferoffset = 0;
8718         rsurface.batchelement3i = NULL;
8719         rsurface.batchelement3i_indexbuffer = NULL;
8720         rsurface.batchelement3i_bufferoffset = 0;
8721         rsurface.batchelement3s = NULL;
8722         rsurface.batchelement3s_indexbuffer = NULL;
8723         rsurface.batchelement3s_bufferoffset = 0;
8724         rsurface.passcolor4f = NULL;
8725         rsurface.passcolor4f_vertexbuffer = NULL;
8726         rsurface.passcolor4f_bufferoffset = 0;
8727         rsurface.forcecurrenttextureupdate = false;
8728 }
8729
8730 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8731 {
8732         rsurface.entity = r_refdef.scene.worldentity;
8733         rsurface.skeleton = NULL;
8734         rsurface.ent_skinnum = 0;
8735         rsurface.ent_qwskin = -1;
8736         rsurface.ent_flags = entflags;
8737         rsurface.shadertime = r_refdef.scene.time - shadertime;
8738         rsurface.modelnumvertices = numvertices;
8739         rsurface.modelnumtriangles = numtriangles;
8740         rsurface.matrix = *matrix;
8741         rsurface.inversematrix = *inversematrix;
8742         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8743         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8744         R_EntityMatrix(&rsurface.matrix);
8745         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8746         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8747         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8748         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8749         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8750         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8751         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8752         rsurface.frameblend[0].lerp = 1;
8753         rsurface.ent_alttextures = false;
8754         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8755         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8756         rsurface.entityskeletaltransform3x4 = NULL;
8757         rsurface.entityskeletaltransform3x4buffer = NULL;
8758         rsurface.entityskeletaltransform3x4offset = 0;
8759         rsurface.entityskeletaltransform3x4size = 0;
8760         rsurface.entityskeletalnumtransforms = 0;
8761         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8762         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8763         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8764         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8765         if (wanttangents)
8766         {
8767                 rsurface.modelvertex3f = (float *)vertex3f;
8768                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8769                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8770                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8771         }
8772         else if (wantnormals)
8773         {
8774                 rsurface.modelvertex3f = (float *)vertex3f;
8775                 rsurface.modelsvector3f = NULL;
8776                 rsurface.modeltvector3f = NULL;
8777                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8778         }
8779         else
8780         {
8781                 rsurface.modelvertex3f = (float *)vertex3f;
8782                 rsurface.modelsvector3f = NULL;
8783                 rsurface.modeltvector3f = NULL;
8784                 rsurface.modelnormal3f = NULL;
8785         }
8786         rsurface.modelvertexmesh = NULL;
8787         rsurface.modelvertexmesh_vertexbuffer = NULL;
8788         rsurface.modelvertexmesh_bufferoffset = 0;
8789         rsurface.modelvertex3f_vertexbuffer = 0;
8790         rsurface.modelvertex3f_bufferoffset = 0;
8791         rsurface.modelsvector3f_vertexbuffer = 0;
8792         rsurface.modelsvector3f_bufferoffset = 0;
8793         rsurface.modeltvector3f_vertexbuffer = 0;
8794         rsurface.modeltvector3f_bufferoffset = 0;
8795         rsurface.modelnormal3f_vertexbuffer = 0;
8796         rsurface.modelnormal3f_bufferoffset = 0;
8797         rsurface.modelgeneratedvertex = true;
8798         rsurface.modellightmapcolor4f  = (float *)color4f;
8799         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8800         rsurface.modellightmapcolor4f_bufferoffset = 0;
8801         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8802         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8803         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8804         rsurface.modeltexcoordlightmap2f  = NULL;
8805         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8806         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8807         rsurface.modelskeletalindex4ub = NULL;
8808         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8809         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8810         rsurface.modelskeletalweight4ub = NULL;
8811         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8812         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8813         rsurface.modelelement3i = (int *)element3i;
8814         rsurface.modelelement3i_indexbuffer = NULL;
8815         rsurface.modelelement3i_bufferoffset = 0;
8816         rsurface.modelelement3s = (unsigned short *)element3s;
8817         rsurface.modelelement3s_indexbuffer = NULL;
8818         rsurface.modelelement3s_bufferoffset = 0;
8819         rsurface.modellightmapoffsets = NULL;
8820         rsurface.modelsurfaces = NULL;
8821         rsurface.batchgeneratedvertex = false;
8822         rsurface.batchfirstvertex = 0;
8823         rsurface.batchnumvertices = 0;
8824         rsurface.batchfirsttriangle = 0;
8825         rsurface.batchnumtriangles = 0;
8826         rsurface.batchvertex3f  = NULL;
8827         rsurface.batchvertex3f_vertexbuffer = NULL;
8828         rsurface.batchvertex3f_bufferoffset = 0;
8829         rsurface.batchsvector3f = NULL;
8830         rsurface.batchsvector3f_vertexbuffer = NULL;
8831         rsurface.batchsvector3f_bufferoffset = 0;
8832         rsurface.batchtvector3f = NULL;
8833         rsurface.batchtvector3f_vertexbuffer = NULL;
8834         rsurface.batchtvector3f_bufferoffset = 0;
8835         rsurface.batchnormal3f  = NULL;
8836         rsurface.batchnormal3f_vertexbuffer = NULL;
8837         rsurface.batchnormal3f_bufferoffset = 0;
8838         rsurface.batchlightmapcolor4f = NULL;
8839         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8840         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8841         rsurface.batchtexcoordtexture2f = NULL;
8842         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8843         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8844         rsurface.batchtexcoordlightmap2f = NULL;
8845         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8846         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8847         rsurface.batchskeletalindex4ub = NULL;
8848         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8849         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8850         rsurface.batchskeletalweight4ub = NULL;
8851         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8852         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8853         rsurface.batchvertexmesh = NULL;
8854         rsurface.batchvertexmesh_vertexbuffer = NULL;
8855         rsurface.batchvertexmesh_bufferoffset = 0;
8856         rsurface.batchelement3i = NULL;
8857         rsurface.batchelement3i_indexbuffer = NULL;
8858         rsurface.batchelement3i_bufferoffset = 0;
8859         rsurface.batchelement3s = NULL;
8860         rsurface.batchelement3s_indexbuffer = NULL;
8861         rsurface.batchelement3s_bufferoffset = 0;
8862         rsurface.passcolor4f = NULL;
8863         rsurface.passcolor4f_vertexbuffer = NULL;
8864         rsurface.passcolor4f_bufferoffset = 0;
8865         rsurface.forcecurrenttextureupdate = true;
8866
8867         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8868         {
8869                 if ((wantnormals || wanttangents) && !normal3f)
8870                 {
8871                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8872                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8873                 }
8874                 if (wanttangents && !svector3f)
8875                 {
8876                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8877                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8878                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8879                 }
8880         }
8881 }
8882
8883 float RSurf_FogPoint(const float *v)
8884 {
8885         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8886         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8887         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8888         float FogHeightFade = r_refdef.fogheightfade;
8889         float fogfrac;
8890         unsigned int fogmasktableindex;
8891         if (r_refdef.fogplaneviewabove)
8892                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8893         else
8894                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8895         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8896         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8897 }
8898
8899 float RSurf_FogVertex(const float *v)
8900 {
8901         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8902         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8903         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8904         float FogHeightFade = rsurface.fogheightfade;
8905         float fogfrac;
8906         unsigned int fogmasktableindex;
8907         if (r_refdef.fogplaneviewabove)
8908                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8909         else
8910                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8911         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8912         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8913 }
8914
8915 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8916 {
8917         int i;
8918         for (i = 0;i < numelements;i++)
8919                 outelement3i[i] = inelement3i[i] + adjust;
8920 }
8921
8922 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8923 extern cvar_t gl_vbo;
8924 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8925 {
8926         int deformindex;
8927         int firsttriangle;
8928         int numtriangles;
8929         int firstvertex;
8930         int endvertex;
8931         int numvertices;
8932         int surfacefirsttriangle;
8933         int surfacenumtriangles;
8934         int surfacefirstvertex;
8935         int surfaceendvertex;
8936         int surfacenumvertices;
8937         int batchnumsurfaces = texturenumsurfaces;
8938         int batchnumvertices;
8939         int batchnumtriangles;
8940         int needsupdate;
8941         int i, j;
8942         qboolean gaps;
8943         qboolean dynamicvertex;
8944         float amplitude;
8945         float animpos;
8946         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8947         float waveparms[4];
8948         unsigned char *ub;
8949         q3shaderinfo_deform_t *deform;
8950         const msurface_t *surface, *firstsurface;
8951         r_vertexmesh_t *vertexmesh;
8952         if (!texturenumsurfaces)
8953                 return;
8954         // find vertex range of this surface batch
8955         gaps = false;
8956         firstsurface = texturesurfacelist[0];
8957         firsttriangle = firstsurface->num_firsttriangle;
8958         batchnumvertices = 0;
8959         batchnumtriangles = 0;
8960         firstvertex = endvertex = firstsurface->num_firstvertex;
8961         for (i = 0;i < texturenumsurfaces;i++)
8962         {
8963                 surface = texturesurfacelist[i];
8964                 if (surface != firstsurface + i)
8965                         gaps = true;
8966                 surfacefirstvertex = surface->num_firstvertex;
8967                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8968                 surfacenumvertices = surface->num_vertices;
8969                 surfacenumtriangles = surface->num_triangles;
8970                 if (firstvertex > surfacefirstvertex)
8971                         firstvertex = surfacefirstvertex;
8972                 if (endvertex < surfaceendvertex)
8973                         endvertex = surfaceendvertex;
8974                 batchnumvertices += surfacenumvertices;
8975                 batchnumtriangles += surfacenumtriangles;
8976         }
8977
8978         r_refdef.stats[r_stat_batch_batches]++;
8979         if (gaps)
8980                 r_refdef.stats[r_stat_batch_withgaps]++;
8981         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8982         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8983         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8984
8985         // we now know the vertex range used, and if there are any gaps in it
8986         rsurface.batchfirstvertex = firstvertex;
8987         rsurface.batchnumvertices = endvertex - firstvertex;
8988         rsurface.batchfirsttriangle = firsttriangle;
8989         rsurface.batchnumtriangles = batchnumtriangles;
8990
8991         // this variable holds flags for which properties have been updated that
8992         // may require regenerating vertexmesh array...
8993         needsupdate = 0;
8994
8995         // check if any dynamic vertex processing must occur
8996         dynamicvertex = false;
8997
8998         // a cvar to force the dynamic vertex path to be taken, for debugging
8999         if (r_batch_debugdynamicvertexpath.integer)
9000         {
9001                 if (!dynamicvertex)
9002                 {
9003                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9004                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9005                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9006                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9007                 }
9008                 dynamicvertex = true;
9009         }
9010
9011         // if there is a chance of animated vertex colors, it's a dynamic batch
9012         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9013         {
9014                 if (!dynamicvertex)
9015                 {
9016                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9017                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9018                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9019                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9020                 }
9021                 dynamicvertex = true;
9022                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9023         }
9024
9025         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9026         {
9027                 switch (deform->deform)
9028                 {
9029                 default:
9030                 case Q3DEFORM_PROJECTIONSHADOW:
9031                 case Q3DEFORM_TEXT0:
9032                 case Q3DEFORM_TEXT1:
9033                 case Q3DEFORM_TEXT2:
9034                 case Q3DEFORM_TEXT3:
9035                 case Q3DEFORM_TEXT4:
9036                 case Q3DEFORM_TEXT5:
9037                 case Q3DEFORM_TEXT6:
9038                 case Q3DEFORM_TEXT7:
9039                 case Q3DEFORM_NONE:
9040                         break;
9041                 case Q3DEFORM_AUTOSPRITE:
9042                         if (!dynamicvertex)
9043                         {
9044                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9045                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9046                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9047                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9048                         }
9049                         dynamicvertex = true;
9050                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9051                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9052                         break;
9053                 case Q3DEFORM_AUTOSPRITE2:
9054                         if (!dynamicvertex)
9055                         {
9056                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9057                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9058                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9059                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9060                         }
9061                         dynamicvertex = true;
9062                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9063                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9064                         break;
9065                 case Q3DEFORM_NORMAL:
9066                         if (!dynamicvertex)
9067                         {
9068                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9069                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9070                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9071                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9072                         }
9073                         dynamicvertex = true;
9074                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9075                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9076                         break;
9077                 case Q3DEFORM_WAVE:
9078                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9079                                 break; // if wavefunc is a nop, ignore this transform
9080                         if (!dynamicvertex)
9081                         {
9082                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9083                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9084                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9085                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9086                         }
9087                         dynamicvertex = true;
9088                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9089                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9090                         break;
9091                 case Q3DEFORM_BULGE:
9092                         if (!dynamicvertex)
9093                         {
9094                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9095                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9096                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9097                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9098                         }
9099                         dynamicvertex = true;
9100                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9101                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9102                         break;
9103                 case Q3DEFORM_MOVE:
9104                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9105                                 break; // if wavefunc is a nop, ignore this transform
9106                         if (!dynamicvertex)
9107                         {
9108                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9109                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9110                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9111                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9112                         }
9113                         dynamicvertex = true;
9114                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9115                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9116                         break;
9117                 }
9118         }
9119         if (rsurface.texture->materialshaderpass)
9120         {
9121                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9122                 {
9123                 default:
9124                 case Q3TCGEN_TEXTURE:
9125                         break;
9126                 case Q3TCGEN_LIGHTMAP:
9127                         if (!dynamicvertex)
9128                         {
9129                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9130                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9131                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9132                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9133                         }
9134                         dynamicvertex = true;
9135                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9136                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9137                         break;
9138                 case Q3TCGEN_VECTOR:
9139                         if (!dynamicvertex)
9140                         {
9141                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9142                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9143                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9144                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9145                         }
9146                         dynamicvertex = true;
9147                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9148                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9149                         break;
9150                 case Q3TCGEN_ENVIRONMENT:
9151                         if (!dynamicvertex)
9152                         {
9153                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9154                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9155                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9156                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9157                         }
9158                         dynamicvertex = true;
9159                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9160                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9161                         break;
9162                 }
9163                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9164                 {
9165                         if (!dynamicvertex)
9166                         {
9167                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9168                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9169                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9170                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9171                         }
9172                         dynamicvertex = true;
9173                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9174                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9175                 }
9176         }
9177
9178         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9179         {
9180                 if (!dynamicvertex)
9181                 {
9182                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9183                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9184                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9185                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9186                 }
9187                 dynamicvertex = true;
9188                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9189         }
9190
9191         // when the model data has no vertex buffer (dynamic mesh), we need to
9192         // eliminate gaps
9193         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9194                 batchneed |= BATCHNEED_NOGAPS;
9195
9196         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9197         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9198         // we ensure this by treating the vertex batch as dynamic...
9199         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9200         {
9201                 if (!dynamicvertex)
9202                 {
9203                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9204                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9205                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9206                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9207                 }
9208                 dynamicvertex = true;
9209         }
9210
9211         if (dynamicvertex)
9212         {
9213                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9214                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9215                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9216                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9217                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9218                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9219                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9220                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9221         }
9222
9223         // if needsupdate, we have to do a dynamic vertex batch for sure
9224         if (needsupdate & batchneed)
9225         {
9226                 if (!dynamicvertex)
9227                 {
9228                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9229                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9230                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9231                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9232                 }
9233                 dynamicvertex = true;
9234         }
9235
9236         // see if we need to build vertexmesh from arrays
9237         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9238         {
9239                 if (!dynamicvertex)
9240                 {
9241                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9242                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9243                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9244                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9245                 }
9246                 dynamicvertex = true;
9247         }
9248
9249         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9250         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9251                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9252
9253         rsurface.batchvertex3f = rsurface.modelvertex3f;
9254         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9255         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9256         rsurface.batchsvector3f = rsurface.modelsvector3f;
9257         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9258         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9259         rsurface.batchtvector3f = rsurface.modeltvector3f;
9260         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9261         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9262         rsurface.batchnormal3f = rsurface.modelnormal3f;
9263         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9264         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9265         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9266         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9267         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9268         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9269         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9270         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9271         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9272         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9273         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9274         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9275         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9276         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9277         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9278         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9279         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9280         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9281         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9282         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9283         rsurface.batchelement3i = rsurface.modelelement3i;
9284         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9285         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9286         rsurface.batchelement3s = rsurface.modelelement3s;
9287         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9288         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9289         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9290         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9291         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9292         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9293         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9294
9295         // if any dynamic vertex processing has to occur in software, we copy the
9296         // entire surface list together before processing to rebase the vertices
9297         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9298         //
9299         // if any gaps exist and we do not have a static vertex buffer, we have to
9300         // copy the surface list together to avoid wasting upload bandwidth on the
9301         // vertices in the gaps.
9302         //
9303         // if gaps exist and we have a static vertex buffer, we can choose whether
9304         // to combine the index buffer ranges into one dynamic index buffer or
9305         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9306         //
9307         // in many cases the batch is reduced to one draw call.
9308
9309         rsurface.batchmultidraw = false;
9310         rsurface.batchmultidrawnumsurfaces = 0;
9311         rsurface.batchmultidrawsurfacelist = NULL;
9312
9313         if (!dynamicvertex)
9314         {
9315                 // static vertex data, just set pointers...
9316                 rsurface.batchgeneratedvertex = false;
9317                 // if there are gaps, we want to build a combined index buffer,
9318                 // otherwise use the original static buffer with an appropriate offset
9319                 if (gaps)
9320                 {
9321                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9322                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9323                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9324                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9325                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9326                         {
9327                                 rsurface.batchmultidraw = true;
9328                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9329                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9330                                 return;
9331                         }
9332                         // build a new triangle elements array for this batch
9333                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9334                         rsurface.batchfirsttriangle = 0;
9335                         numtriangles = 0;
9336                         for (i = 0;i < texturenumsurfaces;i++)
9337                         {
9338                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9339                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9340                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9341                                 numtriangles += surfacenumtriangles;
9342                         }
9343                         rsurface.batchelement3i_indexbuffer = NULL;
9344                         rsurface.batchelement3i_bufferoffset = 0;
9345                         rsurface.batchelement3s = NULL;
9346                         rsurface.batchelement3s_indexbuffer = NULL;
9347                         rsurface.batchelement3s_bufferoffset = 0;
9348                         if (endvertex <= 65536)
9349                         {
9350                                 // make a 16bit (unsigned short) index array if possible
9351                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9352                                 for (i = 0;i < numtriangles*3;i++)
9353                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9354                         }
9355                         // upload buffer data for the copytriangles batch
9356                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9357                         {
9358                                 if (rsurface.batchelement3s)
9359                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9360                                 else if (rsurface.batchelement3i)
9361                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9362                         }
9363                 }
9364                 else
9365                 {
9366                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9367                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9368                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9369                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9370                 }
9371                 return;
9372         }
9373
9374         // something needs software processing, do it for real...
9375         // we only directly handle separate array data in this case and then
9376         // generate interleaved data if needed...
9377         rsurface.batchgeneratedvertex = true;
9378         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9379         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9380         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9381         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9382
9383         // now copy the vertex data into a combined array and make an index array
9384         // (this is what Quake3 does all the time)
9385         // we also apply any skeletal animation here that would have been done in
9386         // the vertex shader, because most of the dynamic vertex animation cases
9387         // need actual vertex positions and normals
9388         //if (dynamicvertex)
9389         {
9390                 rsurface.batchvertexmesh = NULL;
9391                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9392                 rsurface.batchvertexmesh_bufferoffset = 0;
9393                 rsurface.batchvertex3f = NULL;
9394                 rsurface.batchvertex3f_vertexbuffer = NULL;
9395                 rsurface.batchvertex3f_bufferoffset = 0;
9396                 rsurface.batchsvector3f = NULL;
9397                 rsurface.batchsvector3f_vertexbuffer = NULL;
9398                 rsurface.batchsvector3f_bufferoffset = 0;
9399                 rsurface.batchtvector3f = NULL;
9400                 rsurface.batchtvector3f_vertexbuffer = NULL;
9401                 rsurface.batchtvector3f_bufferoffset = 0;
9402                 rsurface.batchnormal3f = NULL;
9403                 rsurface.batchnormal3f_vertexbuffer = NULL;
9404                 rsurface.batchnormal3f_bufferoffset = 0;
9405                 rsurface.batchlightmapcolor4f = NULL;
9406                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9407                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9408                 rsurface.batchtexcoordtexture2f = NULL;
9409                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9410                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9411                 rsurface.batchtexcoordlightmap2f = NULL;
9412                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9413                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9414                 rsurface.batchskeletalindex4ub = NULL;
9415                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9416                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9417                 rsurface.batchskeletalweight4ub = NULL;
9418                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9419                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9420                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9421                 rsurface.batchelement3i_indexbuffer = NULL;
9422                 rsurface.batchelement3i_bufferoffset = 0;
9423                 rsurface.batchelement3s = NULL;
9424                 rsurface.batchelement3s_indexbuffer = NULL;
9425                 rsurface.batchelement3s_bufferoffset = 0;
9426                 rsurface.batchskeletaltransform3x4buffer = NULL;
9427                 rsurface.batchskeletaltransform3x4offset = 0;
9428                 rsurface.batchskeletaltransform3x4size = 0;
9429                 // we'll only be setting up certain arrays as needed
9430                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9431                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9432                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9433                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9434                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9435                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9437                 {
9438                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9439                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9440                 }
9441                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9442                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9443                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9444                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9445                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9446                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9447                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9448                 {
9449                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9450                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9451                 }
9452                 numvertices = 0;
9453                 numtriangles = 0;
9454                 for (i = 0;i < texturenumsurfaces;i++)
9455                 {
9456                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9457                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9458                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9459                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9460                         // copy only the data requested
9461                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9462                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9463                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9464                         {
9465                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9466                                 {
9467                                         if (rsurface.batchvertex3f)
9468                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9469                                         else
9470                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9471                                 }
9472                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9473                                 {
9474                                         if (rsurface.modelnormal3f)
9475                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9476                                         else
9477                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9478                                 }
9479                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9480                                 {
9481                                         if (rsurface.modelsvector3f)
9482                                         {
9483                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9484                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9485                                         }
9486                                         else
9487                                         {
9488                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9489                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9490                                         }
9491                                 }
9492                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9493                                 {
9494                                         if (rsurface.modellightmapcolor4f)
9495                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9496                                         else
9497                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9498                                 }
9499                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9500                                 {
9501                                         if (rsurface.modeltexcoordtexture2f)
9502                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9503                                         else
9504                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9505                                 }
9506                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9507                                 {
9508                                         if (rsurface.modeltexcoordlightmap2f)
9509                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9510                                         else
9511                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9512                                 }
9513                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9514                                 {
9515                                         if (rsurface.modelskeletalindex4ub)
9516                                         {
9517                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9518                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9519                                         }
9520                                         else
9521                                         {
9522                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9523                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9524                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9525                                                 for (j = 0;j < surfacenumvertices;j++)
9526                                                         ub[j*4] = 255;
9527                                         }
9528                                 }
9529                         }
9530                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9531                         numvertices += surfacenumvertices;
9532                         numtriangles += surfacenumtriangles;
9533                 }
9534
9535                 // generate a 16bit index array as well if possible
9536                 // (in general, dynamic batches fit)
9537                 if (numvertices <= 65536)
9538                 {
9539                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9540                         for (i = 0;i < numtriangles*3;i++)
9541                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9542                 }
9543
9544                 // since we've copied everything, the batch now starts at 0
9545                 rsurface.batchfirstvertex = 0;
9546                 rsurface.batchnumvertices = batchnumvertices;
9547                 rsurface.batchfirsttriangle = 0;
9548                 rsurface.batchnumtriangles = batchnumtriangles;
9549         }
9550
9551         // apply skeletal animation that would have been done in the vertex shader
9552         if (rsurface.batchskeletaltransform3x4)
9553         {
9554                 const unsigned char *si;
9555                 const unsigned char *sw;
9556                 const float *t[4];
9557                 const float *b = rsurface.batchskeletaltransform3x4;
9558                 float *vp, *vs, *vt, *vn;
9559                 float w[4];
9560                 float m[3][4], n[3][4];
9561                 float tp[3], ts[3], tt[3], tn[3];
9562                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9563                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9564                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9565                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9566                 si = rsurface.batchskeletalindex4ub;
9567                 sw = rsurface.batchskeletalweight4ub;
9568                 vp = rsurface.batchvertex3f;
9569                 vs = rsurface.batchsvector3f;
9570                 vt = rsurface.batchtvector3f;
9571                 vn = rsurface.batchnormal3f;
9572                 memset(m[0], 0, sizeof(m));
9573                 memset(n[0], 0, sizeof(n));
9574                 for (i = 0;i < batchnumvertices;i++)
9575                 {
9576                         t[0] = b + si[0]*12;
9577                         if (sw[0] == 255)
9578                         {
9579                                 // common case - only one matrix
9580                                 m[0][0] = t[0][ 0];
9581                                 m[0][1] = t[0][ 1];
9582                                 m[0][2] = t[0][ 2];
9583                                 m[0][3] = t[0][ 3];
9584                                 m[1][0] = t[0][ 4];
9585                                 m[1][1] = t[0][ 5];
9586                                 m[1][2] = t[0][ 6];
9587                                 m[1][3] = t[0][ 7];
9588                                 m[2][0] = t[0][ 8];
9589                                 m[2][1] = t[0][ 9];
9590                                 m[2][2] = t[0][10];
9591                                 m[2][3] = t[0][11];
9592                         }
9593                         else if (sw[2] + sw[3])
9594                         {
9595                                 // blend 4 matrices
9596                                 t[1] = b + si[1]*12;
9597                                 t[2] = b + si[2]*12;
9598                                 t[3] = b + si[3]*12;
9599                                 w[0] = sw[0] * (1.0f / 255.0f);
9600                                 w[1] = sw[1] * (1.0f / 255.0f);
9601                                 w[2] = sw[2] * (1.0f / 255.0f);
9602                                 w[3] = sw[3] * (1.0f / 255.0f);
9603                                 // blend the matrices
9604                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9605                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9606                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9607                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9608                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9609                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9610                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9611                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9612                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9613                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9614                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9615                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9616                         }
9617                         else
9618                         {
9619                                 // blend 2 matrices
9620                                 t[1] = b + si[1]*12;
9621                                 w[0] = sw[0] * (1.0f / 255.0f);
9622                                 w[1] = sw[1] * (1.0f / 255.0f);
9623                                 // blend the matrices
9624                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9625                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9626                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9627                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9628                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9629                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9630                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9631                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9632                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9633                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9634                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9635                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9636                         }
9637                         si += 4;
9638                         sw += 4;
9639                         // modify the vertex
9640                         VectorCopy(vp, tp);
9641                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9642                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9643                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9644                         vp += 3;
9645                         if (vn)
9646                         {
9647                                 // the normal transformation matrix is a set of cross products...
9648                                 CrossProduct(m[1], m[2], n[0]);
9649                                 CrossProduct(m[2], m[0], n[1]);
9650                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9651                                 VectorCopy(vn, tn);
9652                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9653                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9654                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9655                                 VectorNormalize(vn);
9656                                 vn += 3;
9657                                 if (vs)
9658                                 {
9659                                         VectorCopy(vs, ts);
9660                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9661                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9662                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9663                                         VectorNormalize(vs);
9664                                         vs += 3;
9665                                         VectorCopy(vt, tt);
9666                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9667                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9668                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9669                                         VectorNormalize(vt);
9670                                         vt += 3;
9671                                 }
9672                         }
9673                 }
9674                 rsurface.batchskeletaltransform3x4 = NULL;
9675                 rsurface.batchskeletalnumtransforms = 0;
9676         }
9677
9678         // q1bsp surfaces rendered in vertex color mode have to have colors
9679         // calculated based on lightstyles
9680         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9681         {
9682                 // generate color arrays for the surfaces in this list
9683                 int c[4];
9684                 int scale;
9685                 int size3;
9686                 const int *offsets;
9687                 const unsigned char *lm;
9688                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9689                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9690                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9691                 numvertices = 0;
9692                 for (i = 0;i < texturenumsurfaces;i++)
9693                 {
9694                         surface = texturesurfacelist[i];
9695                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9696                         surfacenumvertices = surface->num_vertices;
9697                         if (surface->lightmapinfo->samples)
9698                         {
9699                                 for (j = 0;j < surfacenumvertices;j++)
9700                                 {
9701                                         lm = surface->lightmapinfo->samples + offsets[j];
9702                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9703                                         VectorScale(lm, scale, c);
9704                                         if (surface->lightmapinfo->styles[1] != 255)
9705                                         {
9706                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9707                                                 lm += size3;
9708                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9709                                                 VectorMA(c, scale, lm, c);
9710                                                 if (surface->lightmapinfo->styles[2] != 255)
9711                                                 {
9712                                                         lm += size3;
9713                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9714                                                         VectorMA(c, scale, lm, c);
9715                                                         if (surface->lightmapinfo->styles[3] != 255)
9716                                                         {
9717                                                                 lm += size3;
9718                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9719                                                                 VectorMA(c, scale, lm, c);
9720                                                         }
9721                                                 }
9722                                         }
9723                                         c[0] >>= 7;
9724                                         c[1] >>= 7;
9725                                         c[2] >>= 7;
9726                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
9727                                         numvertices++;
9728                                 }
9729                         }
9730                         else
9731                         {
9732                                 for (j = 0;j < surfacenumvertices;j++)
9733                                 {
9734                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9735                                         numvertices++;
9736                                 }
9737                         }
9738                 }
9739         }
9740
9741         // if vertices are deformed (sprite flares and things in maps, possibly
9742         // water waves, bulges and other deformations), modify the copied vertices
9743         // in place
9744         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9745         {
9746                 float scale;
9747                 switch (deform->deform)
9748                 {
9749                 default:
9750                 case Q3DEFORM_PROJECTIONSHADOW:
9751                 case Q3DEFORM_TEXT0:
9752                 case Q3DEFORM_TEXT1:
9753                 case Q3DEFORM_TEXT2:
9754                 case Q3DEFORM_TEXT3:
9755                 case Q3DEFORM_TEXT4:
9756                 case Q3DEFORM_TEXT5:
9757                 case Q3DEFORM_TEXT6:
9758                 case Q3DEFORM_TEXT7:
9759                 case Q3DEFORM_NONE:
9760                         break;
9761                 case Q3DEFORM_AUTOSPRITE:
9762                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9763                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9764                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9765                         VectorNormalize(newforward);
9766                         VectorNormalize(newright);
9767                         VectorNormalize(newup);
9768 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9769 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9770 //                      rsurface.batchvertex3f_bufferoffset = 0;
9771 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9772 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9773 //                      rsurface.batchsvector3f_bufferoffset = 0;
9774 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9775 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9776 //                      rsurface.batchtvector3f_bufferoffset = 0;
9777 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9778 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9779 //                      rsurface.batchnormal3f_bufferoffset = 0;
9780                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9781                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9782                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9783                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9784                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9785                         // a single autosprite surface can contain multiple sprites...
9786                         for (j = 0;j < batchnumvertices - 3;j += 4)
9787                         {
9788                                 VectorClear(center);
9789                                 for (i = 0;i < 4;i++)
9790                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9791                                 VectorScale(center, 0.25f, center);
9792                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9793                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9794                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9795                                 for (i = 0;i < 4;i++)
9796                                 {
9797                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9798                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9799                                 }
9800                         }
9801                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9802                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9803                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9804                         break;
9805                 case Q3DEFORM_AUTOSPRITE2:
9806                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9807                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9808                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9809                         VectorNormalize(newforward);
9810                         VectorNormalize(newright);
9811                         VectorNormalize(newup);
9812 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9813 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9814 //                      rsurface.batchvertex3f_bufferoffset = 0;
9815                         {
9816                                 const float *v1, *v2;
9817                                 vec3_t start, end;
9818                                 float f, l;
9819                                 struct
9820                                 {
9821                                         float length2;
9822                                         const float *v1;
9823                                         const float *v2;
9824                                 }
9825                                 shortest[2];
9826                                 memset(shortest, 0, sizeof(shortest));
9827                                 // a single autosprite surface can contain multiple sprites...
9828                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9829                                 {
9830                                         VectorClear(center);
9831                                         for (i = 0;i < 4;i++)
9832                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9833                                         VectorScale(center, 0.25f, center);
9834                                         // find the two shortest edges, then use them to define the
9835                                         // axis vectors for rotating around the central axis
9836                                         for (i = 0;i < 6;i++)
9837                                         {
9838                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9839                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9840                                                 l = VectorDistance2(v1, v2);
9841                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9842                                                 if (v1[2] != v2[2])
9843                                                         l += (1.0f / 1024.0f);
9844                                                 if (shortest[0].length2 > l || i == 0)
9845                                                 {
9846                                                         shortest[1] = shortest[0];
9847                                                         shortest[0].length2 = l;
9848                                                         shortest[0].v1 = v1;
9849                                                         shortest[0].v2 = v2;
9850                                                 }
9851                                                 else if (shortest[1].length2 > l || i == 1)
9852                                                 {
9853                                                         shortest[1].length2 = l;
9854                                                         shortest[1].v1 = v1;
9855                                                         shortest[1].v2 = v2;
9856                                                 }
9857                                         }
9858                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9859                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9860                                         // this calculates the right vector from the shortest edge
9861                                         // and the up vector from the edge midpoints
9862                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9863                                         VectorNormalize(right);
9864                                         VectorSubtract(end, start, up);
9865                                         VectorNormalize(up);
9866                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9867                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9868                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9869                                         VectorNegate(forward, forward);
9870                                         VectorReflect(forward, 0, up, forward);
9871                                         VectorNormalize(forward);
9872                                         CrossProduct(up, forward, newright);
9873                                         VectorNormalize(newright);
9874                                         // rotate the quad around the up axis vector, this is made
9875                                         // especially easy by the fact we know the quad is flat,
9876                                         // so we only have to subtract the center position and
9877                                         // measure distance along the right vector, and then
9878                                         // multiply that by the newright vector and add back the
9879                                         // center position
9880                                         // we also need to subtract the old position to undo the
9881                                         // displacement from the center, which we do with a
9882                                         // DotProduct, the subtraction/addition of center is also
9883                                         // optimized into DotProducts here
9884                                         l = DotProduct(right, center);
9885                                         for (i = 0;i < 4;i++)
9886                                         {
9887                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9888                                                 f = DotProduct(right, v1) - l;
9889                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9890                                         }
9891                                 }
9892                         }
9893                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9894                         {
9895 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9896 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9897 //                              rsurface.batchnormal3f_bufferoffset = 0;
9898                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9899                         }
9900                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9901                         {
9902 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9903 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9904 //                              rsurface.batchsvector3f_bufferoffset = 0;
9905 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9906 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9907 //                              rsurface.batchtvector3f_bufferoffset = 0;
9908                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9909                         }
9910                         break;
9911                 case Q3DEFORM_NORMAL:
9912                         // deform the normals to make reflections wavey
9913                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9914                         rsurface.batchnormal3f_vertexbuffer = NULL;
9915                         rsurface.batchnormal3f_bufferoffset = 0;
9916                         for (j = 0;j < batchnumvertices;j++)
9917                         {
9918                                 float vertex[3];
9919                                 float *normal = rsurface.batchnormal3f + 3*j;
9920                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9921                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9922                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9923                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9924                                 VectorNormalize(normal);
9925                         }
9926                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9927                         {
9928 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9929 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9930 //                              rsurface.batchsvector3f_bufferoffset = 0;
9931 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9932 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9933 //                              rsurface.batchtvector3f_bufferoffset = 0;
9934                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9935                         }
9936                         break;
9937                 case Q3DEFORM_WAVE:
9938                         // deform vertex array to make wavey water and flags and such
9939                         waveparms[0] = deform->waveparms[0];
9940                         waveparms[1] = deform->waveparms[1];
9941                         waveparms[2] = deform->waveparms[2];
9942                         waveparms[3] = deform->waveparms[3];
9943                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9944                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9945                         // this is how a divisor of vertex influence on deformation
9946                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9947                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9948 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9949 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9950 //                      rsurface.batchvertex3f_bufferoffset = 0;
9951 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9952 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9953 //                      rsurface.batchnormal3f_bufferoffset = 0;
9954                         for (j = 0;j < batchnumvertices;j++)
9955                         {
9956                                 // if the wavefunc depends on time, evaluate it per-vertex
9957                                 if (waveparms[3])
9958                                 {
9959                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9960                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9961                                 }
9962                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9963                         }
9964                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9965                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9966                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9967                         {
9968 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9969 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9970 //                              rsurface.batchsvector3f_bufferoffset = 0;
9971 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9972 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9973 //                              rsurface.batchtvector3f_bufferoffset = 0;
9974                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9975                         }
9976                         break;
9977                 case Q3DEFORM_BULGE:
9978                         // deform vertex array to make the surface have moving bulges
9979 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9980 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9981 //                      rsurface.batchvertex3f_bufferoffset = 0;
9982 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9983 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9984 //                      rsurface.batchnormal3f_bufferoffset = 0;
9985                         for (j = 0;j < batchnumvertices;j++)
9986                         {
9987                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9988                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9989                         }
9990                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9991                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9992                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9993                         {
9994 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9995 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9996 //                              rsurface.batchsvector3f_bufferoffset = 0;
9997 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9998 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9999 //                              rsurface.batchtvector3f_bufferoffset = 0;
10000                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
10001                         }
10002                         break;
10003                 case Q3DEFORM_MOVE:
10004                         // deform vertex array
10005                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10006                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10007                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10008                         VectorScale(deform->parms, scale, waveparms);
10009 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10010 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10011 //                      rsurface.batchvertex3f_bufferoffset = 0;
10012                         for (j = 0;j < batchnumvertices;j++)
10013                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10014                         break;
10015                 }
10016         }
10017
10018         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10019         {
10020         // generate texcoords based on the chosen texcoord source
10021                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10022                 {
10023                 default:
10024                 case Q3TCGEN_TEXTURE:
10025                         break;
10026                 case Q3TCGEN_LIGHTMAP:
10027         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10028         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10029         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10030                         if (rsurface.batchtexcoordlightmap2f)
10031                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10032                         break;
10033                 case Q3TCGEN_VECTOR:
10034         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10035         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10036         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10037                         for (j = 0;j < batchnumvertices;j++)
10038                         {
10039                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10040                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10041                         }
10042                         break;
10043                 case Q3TCGEN_ENVIRONMENT:
10044                         // make environment reflections using a spheremap
10045                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10046                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10047                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10048                         for (j = 0;j < batchnumvertices;j++)
10049                         {
10050                                 // identical to Q3A's method, but executed in worldspace so
10051                                 // carried models can be shiny too
10052
10053                                 float viewer[3], d, reflected[3], worldreflected[3];
10054
10055                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10056                                 // VectorNormalize(viewer);
10057
10058                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10059
10060                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10061                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10062                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10063                                 // note: this is proportinal to viewer, so we can normalize later
10064
10065                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10066                                 VectorNormalize(worldreflected);
10067
10068                                 // note: this sphere map only uses world x and z!
10069                                 // so positive and negative y will LOOK THE SAME.
10070                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10071                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10072                         }
10073                         break;
10074                 }
10075                 // the only tcmod that needs software vertex processing is turbulent, so
10076                 // check for it here and apply the changes if needed
10077                 // and we only support that as the first one
10078                 // (handling a mixture of turbulent and other tcmods would be problematic
10079                 //  without punting it entirely to a software path)
10080                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10081                 {
10082                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10083                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10084         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10085         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10086         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10087                         for (j = 0;j < batchnumvertices;j++)
10088                         {
10089                                 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10090                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10091                         }
10092                 }
10093         }
10094
10095         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10096         {
10097                 // convert the modified arrays to vertex structs
10098 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10099 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10100 //              rsurface.batchvertexmesh_bufferoffset = 0;
10101                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10102                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10103                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10104                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10105                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10106                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10107                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10108                 {
10109                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10110                         {
10111                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10112                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10113                         }
10114                 }
10115                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10116                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10117                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10118                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10119                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10120                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10121                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10122                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10123                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10124                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10125                 {
10126                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10127                         {
10128                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10129                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10130                         }
10131                 }
10132         }
10133
10134         // upload buffer data for the dynamic batch
10135         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10136         {
10137                 if (rsurface.batchvertexmesh)
10138                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10139                 else
10140                 {
10141                         if (rsurface.batchvertex3f)
10142                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10143                         if (rsurface.batchsvector3f)
10144                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10145                         if (rsurface.batchtvector3f)
10146                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10147                         if (rsurface.batchnormal3f)
10148                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10149                         if (rsurface.batchlightmapcolor4f)
10150                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10151                         if (rsurface.batchtexcoordtexture2f)
10152                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10153                         if (rsurface.batchtexcoordlightmap2f)
10154                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10155                         if (rsurface.batchskeletalindex4ub)
10156                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10157                         if (rsurface.batchskeletalweight4ub)
10158                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10159                 }
10160                 if (rsurface.batchelement3s)
10161                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10162                 else if (rsurface.batchelement3i)
10163                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10164         }
10165 }
10166
10167 void RSurf_DrawBatch(void)
10168 {
10169         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10170         // through the pipeline, killing it earlier in the pipeline would have
10171         // per-surface overhead rather than per-batch overhead, so it's best to
10172         // reject it here, before it hits glDraw.
10173         if (rsurface.batchnumtriangles == 0)
10174                 return;
10175 #if 0
10176         // batch debugging code
10177         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10178         {
10179                 int i;
10180                 int j;
10181                 int c;
10182                 const int *e;
10183                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10184                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10185                 {
10186                         c = e[i];
10187                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10188                         {
10189                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10190                                 {
10191                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10192                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
10193                                         break;
10194                                 }
10195                         }
10196                 }
10197         }
10198 #endif
10199         if (rsurface.batchmultidraw)
10200         {
10201                 // issue multiple draws rather than copying index data
10202                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10203                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10204                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10205                 for (i = 0;i < numsurfaces;)
10206                 {
10207                         // combine consecutive surfaces as one draw
10208                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10209                                 if (surfacelist[j] != surfacelist[k] + 1)
10210                                         break;
10211                         firstvertex = surfacelist[i]->num_firstvertex;
10212                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10213                         firsttriangle = surfacelist[i]->num_firsttriangle;
10214                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10215                         R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10216                         i = j;
10217                 }
10218         }
10219         else
10220         {
10221                 // there is only one consecutive run of index data (may have been combined)
10222                 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10223         }
10224 }
10225
10226 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10227 {
10228         // pick the closest matching water plane
10229         int planeindex, vertexindex, bestplaneindex = -1;
10230         float d, bestd;
10231         vec3_t vert;
10232         const float *v;
10233         r_waterstate_waterplane_t *p;
10234         qboolean prepared = false;
10235         bestd = 0;
10236         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10237         {
10238                 if(p->camera_entity != rsurface.texture->camera_entity)
10239                         continue;
10240                 d = 0;
10241                 if(!prepared)
10242                 {
10243                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10244                         prepared = true;
10245                         if(rsurface.batchnumvertices == 0)
10246                                 break;
10247                 }
10248                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10249                 {
10250                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10251                         d += fabs(PlaneDiff(vert, &p->plane));
10252                 }
10253                 if (bestd > d || bestplaneindex < 0)
10254                 {
10255                         bestd = d;
10256                         bestplaneindex = planeindex;
10257                 }
10258         }
10259         return bestplaneindex;
10260         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10261         // this situation though, as it might be better to render single larger
10262         // batches with useless stuff (backface culled for example) than to
10263         // render multiple smaller batches
10264 }
10265
10266 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10267 {
10268         int i;
10269         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10270         rsurface.passcolor4f_vertexbuffer = 0;
10271         rsurface.passcolor4f_bufferoffset = 0;
10272         for (i = 0;i < rsurface.batchnumvertices;i++)
10273                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10274 }
10275
10276 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10277 {
10278         int i;
10279         float f;
10280         const float *v;
10281         const float *c;
10282         float *c2;
10283         if (rsurface.passcolor4f)
10284         {
10285                 // generate color arrays
10286                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10287                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10288                 rsurface.passcolor4f_vertexbuffer = 0;
10289                 rsurface.passcolor4f_bufferoffset = 0;
10290                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10291                 {
10292                         f = RSurf_FogVertex(v);
10293                         c2[0] = c[0] * f;
10294                         c2[1] = c[1] * f;
10295                         c2[2] = c[2] * f;
10296                         c2[3] = c[3];
10297                 }
10298         }
10299         else
10300         {
10301                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10302                 rsurface.passcolor4f_vertexbuffer = 0;
10303                 rsurface.passcolor4f_bufferoffset = 0;
10304                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10305                 {
10306                         f = RSurf_FogVertex(v);
10307                         c2[0] = f;
10308                         c2[1] = f;
10309                         c2[2] = f;
10310                         c2[3] = 1;
10311                 }
10312         }
10313 }
10314
10315 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10316 {
10317         int i;
10318         float f;
10319         const float *v;
10320         const float *c;
10321         float *c2;
10322         if (!rsurface.passcolor4f)
10323                 return;
10324         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10325         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10326         rsurface.passcolor4f_vertexbuffer = 0;
10327         rsurface.passcolor4f_bufferoffset = 0;
10328         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10329         {
10330                 f = RSurf_FogVertex(v);
10331                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10332                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10333                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10334                 c2[3] = c[3];
10335         }
10336 }
10337
10338 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10339 {
10340         int i;
10341         const float *c;
10342         float *c2;
10343         if (!rsurface.passcolor4f)
10344                 return;
10345         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10346         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10347         rsurface.passcolor4f_vertexbuffer = 0;
10348         rsurface.passcolor4f_bufferoffset = 0;
10349         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10350         {
10351                 c2[0] = c[0] * r;
10352                 c2[1] = c[1] * g;
10353                 c2[2] = c[2] * b;
10354                 c2[3] = c[3] * a;
10355         }
10356 }
10357
10358 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10359 {
10360         int i;
10361         const float *c;
10362         float *c2;
10363         if (!rsurface.passcolor4f)
10364                 return;
10365         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10366         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10367         rsurface.passcolor4f_vertexbuffer = 0;
10368         rsurface.passcolor4f_bufferoffset = 0;
10369         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10370         {
10371                 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10372                 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10373                 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10374                 c2[3] = c[3];
10375         }
10376 }
10377
10378 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10379 {
10380         // TODO: optimize
10381         rsurface.passcolor4f = NULL;
10382         rsurface.passcolor4f_vertexbuffer = 0;
10383         rsurface.passcolor4f_bufferoffset = 0;
10384         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10385         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10386         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10387         GL_Color(r, g, b, a);
10388         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10389         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10390         R_Mesh_TexMatrix(0, NULL);
10391         RSurf_DrawBatch();
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10395 {
10396         // TODO: optimize applyfog && applycolor case
10397         // just apply fog if necessary, and tint the fog color array if necessary
10398         rsurface.passcolor4f = NULL;
10399         rsurface.passcolor4f_vertexbuffer = 0;
10400         rsurface.passcolor4f_bufferoffset = 0;
10401         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10402         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10403         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10404         GL_Color(r, g, b, a);
10405         RSurf_DrawBatch();
10406 }
10407
10408 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10409 {
10410         // TODO: optimize
10411         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10412         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10413         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10414         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10415         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10416         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10417         GL_Color(r, g, b, a);
10418         RSurf_DrawBatch();
10419 }
10420
10421 static void RSurf_DrawBatch_GL11_ClampColor(void)
10422 {
10423         int i;
10424         const float *c1;
10425         float *c2;
10426         if (!rsurface.passcolor4f)
10427                 return;
10428         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10429         {
10430                 c2[0] = bound(0.0f, c1[0], 1.0f);
10431                 c2[1] = bound(0.0f, c1[1], 1.0f);
10432                 c2[2] = bound(0.0f, c1[2], 1.0f);
10433                 c2[3] = bound(0.0f, c1[3], 1.0f);
10434         }
10435 }
10436
10437 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10438 {
10439         int i;
10440         float f;
10441         const float *v;
10442         const float *n;
10443         float *c;
10444         //vec3_t eyedir;
10445
10446         // fake shading
10447         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10448         rsurface.passcolor4f_vertexbuffer = 0;
10449         rsurface.passcolor4f_bufferoffset = 0;
10450         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10451         {
10452                 f = -DotProduct(r_refdef.view.forward, n);
10453                 f = max(0, f);
10454                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10455                 f *= fakelightintensity;
10456                 Vector4Set(c, f, f, f, 1);
10457         }
10458 }
10459
10460 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10461 {
10462         RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10463         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10464         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10465         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10466         GL_Color(r, g, b, a);
10467         RSurf_DrawBatch();
10468 }
10469
10470 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10471 {
10472         int i;
10473         float f;
10474         float alpha;
10475         const float *v;
10476         const float *n;
10477         float *c;
10478         vec3_t ambientcolor;
10479         vec3_t diffusecolor;
10480         vec3_t lightdir;
10481         // TODO: optimize
10482         // model lighting
10483         VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10484         f = 0.5f * lightmapintensity;
10485         ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10486         ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10487         ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10488         diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10489         diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10490         diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10491         alpha = *a;
10492         if (VectorLength2(diffusecolor) > 0)
10493         {
10494                 // q3-style directional shading
10495                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10496                 rsurface.passcolor4f_vertexbuffer = 0;
10497                 rsurface.passcolor4f_bufferoffset = 0;
10498                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10499                 {
10500                         if ((f = DotProduct(n, lightdir)) > 0)
10501                                 VectorMA(ambientcolor, f, diffusecolor, c);
10502                         else
10503                                 VectorCopy(ambientcolor, c);
10504                         c[3] = alpha;
10505                 }
10506                 *r = 1;
10507                 *g = 1;
10508                 *b = 1;
10509                 *a = 1;
10510                 *applycolor = false;
10511         }
10512         else
10513         {
10514                 *r = ambientcolor[0];
10515                 *g = ambientcolor[1];
10516                 *b = ambientcolor[2];
10517                 rsurface.passcolor4f = NULL;
10518                 rsurface.passcolor4f_vertexbuffer = 0;
10519                 rsurface.passcolor4f_bufferoffset = 0;
10520         }
10521 }
10522
10523 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10524 {
10525         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10526         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10527         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10528         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10529         GL_Color(r, g, b, a);
10530         RSurf_DrawBatch();
10531 }
10532
10533 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10534 {
10535         int i;
10536         float f;
10537         const float *v;
10538         float *c;
10539
10540         // fake shading
10541         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10542         rsurface.passcolor4f_vertexbuffer = 0;
10543         rsurface.passcolor4f_bufferoffset = 0;
10544
10545         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10546         {
10547                 f = 1 - RSurf_FogVertex(v);
10548                 c[0] = r;
10549                 c[1] = g;
10550                 c[2] = b;
10551                 c[3] = f * a;
10552         }
10553 }
10554
10555 void RSurf_SetupDepthAndCulling(void)
10556 {
10557         // submodels are biased to avoid z-fighting with world surfaces that they
10558         // may be exactly overlapping (avoids z-fighting artifacts on certain
10559         // doors and things in Quake maps)
10560         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10561         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10562         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10563         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10564 }
10565
10566 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10567 {
10568         int i, j;
10569         // transparent sky would be ridiculous
10570         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10571                 return;
10572         R_SetupShader_Generic_NoTexture(false, false);
10573         skyrenderlater = true;
10574         RSurf_SetupDepthAndCulling();
10575         GL_DepthMask(true);
10576
10577         // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10578         if (r_sky_scissor.integer)
10579         {
10580                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10581                 for (i = 0; i < texturenumsurfaces; i++)
10582                 {
10583                         const msurface_t *surf = texturesurfacelist[i];
10584                         const float *v;
10585                         float p[3];
10586                         float mins[3], maxs[3];
10587                         int scissor[4];
10588                         for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10589                         {
10590                                 Matrix4x4_Transform(&rsurface.matrix, v, p);
10591                                 if (j > 0)
10592                                 {
10593                                         if (mins[0] > p[0]) mins[0] = p[0];
10594                                         if (mins[1] > p[1]) mins[1] = p[1];
10595                                         if (mins[2] > p[2]) mins[2] = p[2];
10596                                         if (maxs[0] < p[0]) maxs[0] = p[0];
10597                                         if (maxs[1] < p[1]) maxs[1] = p[1];
10598                                         if (maxs[2] < p[2]) maxs[2] = p[2];
10599                                 }
10600                                 else
10601                                 {
10602                                         VectorCopy(p, mins);
10603                                         VectorCopy(p, maxs);
10604                                 }
10605                         }
10606                         if (!R_ScissorForBBox(mins, maxs, scissor))
10607                         {
10608                                 if (skyscissor[2])
10609                                 {
10610                                         if (skyscissor[0] > scissor[0])
10611                                         {
10612                                                 skyscissor[2] += skyscissor[0] - scissor[0];
10613                                                 skyscissor[0] = scissor[0];
10614                                         }
10615                                         if (skyscissor[1] > scissor[1])
10616                                         {
10617                                                 skyscissor[3] += skyscissor[1] - scissor[1];
10618                                                 skyscissor[1] = scissor[1];
10619                                         }
10620                                         if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10621                                                 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10622                                         if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10623                                                 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10624                                 }
10625                                 else
10626                                         Vector4Copy(scissor, skyscissor);
10627                         }
10628                 }
10629         }
10630
10631         // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10632         // skymasking on them, and Quake3 never did sky masking (unlike
10633         // software Quake and software Quake2), so disable the sky masking
10634         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10635         // and skymasking also looks very bad when noclipping outside the
10636         // level, so don't use it then either.
10637         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10638         {
10639                 R_Mesh_ResetTextureState();
10640                 if (skyrendermasked)
10641                 {
10642                         R_SetupShader_DepthOrShadow(false, false, false);
10643                         // depth-only (masking)
10644                         GL_ColorMask(0, 0, 0, 0);
10645                         // just to make sure that braindead drivers don't draw
10646                         // anything despite that colormask...
10647                         GL_BlendFunc(GL_ZERO, GL_ONE);
10648                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10649                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10650                 }
10651                 else
10652                 {
10653                         R_SetupShader_Generic_NoTexture(false, false);
10654                         // fog sky
10655                         GL_BlendFunc(GL_ONE, GL_ZERO);
10656                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10657                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10658                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10659                 }
10660                 RSurf_DrawBatch();
10661                 if (skyrendermasked)
10662                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10663         }
10664         R_Mesh_ResetTextureState();
10665         GL_Color(1, 1, 1, 1);
10666 }
10667
10668 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10669 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10670 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10671 {
10672         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10673                 return;
10674         if (prepass)
10675         {
10676                 // render screenspace normalmap to texture
10677                 GL_DepthMask(true);
10678                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10679                 RSurf_DrawBatch();
10680                 return;
10681         }
10682
10683         // bind lightmap texture
10684
10685         // water/refraction/reflection/camera surfaces have to be handled specially
10686         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10687         {
10688                 int start, end, startplaneindex;
10689                 for (start = 0;start < texturenumsurfaces;start = end)
10690                 {
10691                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10692                         if(startplaneindex < 0)
10693                         {
10694                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10695                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10696                                 end = start + 1;
10697                                 continue;
10698                         }
10699                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10700                                 ;
10701                         // now that we have a batch using the same planeindex, render it
10702                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10703                         {
10704                                 // render water or distortion background
10705                                 GL_DepthMask(true);
10706                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10707                                 RSurf_DrawBatch();
10708                                 // blend surface on top
10709                                 GL_DepthMask(false);
10710                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10711                                 RSurf_DrawBatch();
10712                         }
10713                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10714                         {
10715                                 // render surface with reflection texture as input
10716                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10717                                 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10718                                 RSurf_DrawBatch();
10719                         }
10720                 }
10721                 return;
10722         }
10723
10724         // render surface batch normally
10725         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10726         R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10727         RSurf_DrawBatch();
10728 }
10729
10730 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10731 {
10732         // OpenGL 1.3 path - anything not completely ancient
10733         qboolean applycolor;
10734         qboolean applyfog;
10735         int layerindex;
10736         const texturelayer_t *layer;
10737         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10738         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10739
10740         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10741         {
10742                 vec4_t layercolor;
10743                 int layertexrgbscale;
10744                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10745                 {
10746                         if (layerindex == 0)
10747                                 GL_AlphaTest(true);
10748                         else
10749                         {
10750                                 GL_AlphaTest(false);
10751                                 GL_DepthFunc(GL_EQUAL);
10752                         }
10753                 }
10754                 GL_DepthMask(layer->depthmask && writedepth);
10755                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10756                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10757                 {
10758                         layertexrgbscale = 4;
10759                         VectorScale(layer->color, 0.25f, layercolor);
10760                 }
10761                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10762                 {
10763                         layertexrgbscale = 2;
10764                         VectorScale(layer->color, 0.5f, layercolor);
10765                 }
10766                 else
10767                 {
10768                         layertexrgbscale = 1;
10769                         VectorScale(layer->color, 1.0f, layercolor);
10770                 }
10771                 layercolor[3] = layer->color[3];
10772                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10773                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10774                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10775                 switch (layer->type)
10776                 {
10777                 case TEXTURELAYERTYPE_LITTEXTURE:
10778                         // single-pass lightmapped texture with 2x rgbscale
10779                         R_Mesh_TexBind(0, r_texture_white);
10780                         R_Mesh_TexMatrix(0, NULL);
10781                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10782                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10783                         R_Mesh_TexBind(1, layer->texture);
10784                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10785                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10786                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10787                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10788                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10789                         else if (FAKELIGHT_ENABLED)
10790                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10791                         else if (rsurface.uselightmaptexture)
10792                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10793                         else
10794                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10795                         break;
10796                 case TEXTURELAYERTYPE_TEXTURE:
10797                         // singletexture unlit texture with transparency support
10798                         R_Mesh_TexBind(0, layer->texture);
10799                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10800                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10801                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10802                         R_Mesh_TexBind(1, 0);
10803                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10804                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10805                         break;
10806                 case TEXTURELAYERTYPE_FOG:
10807                         // singletexture fogging
10808                         if (layer->texture)
10809                         {
10810                                 R_Mesh_TexBind(0, layer->texture);
10811                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10812                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10814                         }
10815                         else
10816                         {
10817                                 R_Mesh_TexBind(0, 0);
10818                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10819                         }
10820                         R_Mesh_TexBind(1, 0);
10821                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10822                         // generate a color array for the fog pass
10823                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10824                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10825                         RSurf_DrawBatch();
10826                         break;
10827                 default:
10828                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10829                 }
10830         }
10831         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10832         {
10833                 GL_DepthFunc(GL_LEQUAL);
10834                 GL_AlphaTest(false);
10835         }
10836 }
10837
10838 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10839 {
10840         // OpenGL 1.1 - crusty old voodoo path
10841         qboolean applyfog;
10842         int layerindex;
10843         const texturelayer_t *layer;
10844         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10845         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10846
10847         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10848         {
10849                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10850                 {
10851                         if (layerindex == 0)
10852                                 GL_AlphaTest(true);
10853                         else
10854                         {
10855                                 GL_AlphaTest(false);
10856                                 GL_DepthFunc(GL_EQUAL);
10857                         }
10858                 }
10859                 GL_DepthMask(layer->depthmask && writedepth);
10860                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10861                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10862                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10863                 switch (layer->type)
10864                 {
10865                 case TEXTURELAYERTYPE_LITTEXTURE:
10866                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10867                         {
10868                                 // two-pass lit texture with 2x rgbscale
10869                                 // first the lightmap pass
10870                                 R_Mesh_TexBind(0, r_texture_white);
10871                                 R_Mesh_TexMatrix(0, NULL);
10872                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10873                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10874                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10875                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10876                                 else if (FAKELIGHT_ENABLED)
10877                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10878                                 else if (rsurface.uselightmaptexture)
10879                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10880                                 else
10881                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10882                                 // then apply the texture to it
10883                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10884                                 R_Mesh_TexBind(0, layer->texture);
10885                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10886                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10887                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10888                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
10889                         }
10890                         else
10891                         {
10892                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10893                                 R_Mesh_TexBind(0, layer->texture);
10894                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10895                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10896                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10897                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10898                                         RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10899                                 else if (FAKELIGHT_ENABLED)
10900                                         RSurf_DrawBatch_GL11_FakeLight(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10901                                 else
10902                                         RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10903                         }
10904                         break;
10905                 case TEXTURELAYERTYPE_TEXTURE:
10906                         // singletexture unlit texture with transparency support
10907                         R_Mesh_TexBind(0, layer->texture);
10908                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10909                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10910                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10911                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10912                         break;
10913                 case TEXTURELAYERTYPE_FOG:
10914                         // singletexture fogging
10915                         if (layer->texture)
10916                         {
10917                                 R_Mesh_TexBind(0, layer->texture);
10918                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10919                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10920                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10921                         }
10922                         else
10923                         {
10924                                 R_Mesh_TexBind(0, 0);
10925                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10926                         }
10927                         // generate a color array for the fog pass
10928                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10929                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10930                         RSurf_DrawBatch();
10931                         break;
10932                 default:
10933                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10934                 }
10935         }
10936         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10937         {
10938                 GL_DepthFunc(GL_LEQUAL);
10939                 GL_AlphaTest(false);
10940         }
10941 }
10942
10943 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10944 {
10945         int vi;
10946         int j;
10947         r_vertexgeneric_t *batchvertex;
10948         float c[4];
10949         texture_t *t = rsurface.texture;
10950
10951 //      R_Mesh_ResetTextureState();
10952         R_SetupShader_Generic_NoTexture(false, false);
10953
10954         if(t && t->currentskinframe)
10955         {
10956                 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10957                 c[3] *= t->currentalpha;
10958         }
10959         else
10960         {
10961                 c[0] = 1;
10962                 c[1] = 0;
10963                 c[2] = 1;
10964                 c[3] = 1;
10965         }
10966
10967         if (t->pantstexture || t->shirttexture)
10968         {
10969                 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10970                 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10971                 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10972         }
10973
10974         // brighten it up (as texture value 127 means "unlit")
10975         c[0] *= 2 * r_refdef.view.colorscale;
10976         c[1] *= 2 * r_refdef.view.colorscale;
10977         c[2] *= 2 * r_refdef.view.colorscale;
10978
10979         if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10980                 c[3] *= r_wateralpha.value;
10981
10982         if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10983         {
10984                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10985                 GL_DepthMask(false);
10986         }
10987         else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10988         {
10989                 GL_BlendFunc(GL_ONE, GL_ONE);
10990                 GL_DepthMask(false);
10991         }
10992         else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10993         {
10994                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10995                 GL_DepthMask(false);
10996         }
10997         else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10998         {
10999                 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11000                 GL_DepthMask(false);
11001         }
11002         else
11003         {
11004                 GL_BlendFunc(GL_ONE, GL_ZERO);
11005                 GL_DepthMask(writedepth);
11006         }
11007
11008         if (r_showsurfaces.integer == 3)
11009         {
11010                 rsurface.passcolor4f = NULL;
11011
11012                 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11013                 {
11014                         qboolean applycolor = true;
11015                         float one = 1.0;
11016
11017                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11018
11019                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11020                 }
11021                 else if (FAKELIGHT_ENABLED)
11022                 {
11023                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11024
11025                         RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11026                 }
11027                 else
11028                 {
11029                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11030
11031                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11032                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11033                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11034                         RSurf_DrawBatch_GL11_ApplyAmbient();
11035                 }
11036
11037                 if(!rsurface.passcolor4f)
11038                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11039
11040                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11041                 if(r_refdef.fogenabled)
11042                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11043                 RSurf_DrawBatch_GL11_ClampColor();
11044
11045                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11046                 R_SetupShader_Generic_NoTexture(false, false);
11047                 RSurf_DrawBatch();
11048         }
11049         else if (!r_refdef.view.showdebug)
11050         {
11051                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11053                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11054                 {
11055                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11056                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11057                 }
11058                 R_Mesh_PrepareVertices_Generic_Unlock();
11059                 RSurf_DrawBatch();
11060         }
11061         else if (r_showsurfaces.integer == 4)
11062         {
11063                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11065                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11066                 {
11067                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11068                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11069                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11070                 }
11071                 R_Mesh_PrepareVertices_Generic_Unlock();
11072                 RSurf_DrawBatch();
11073         }
11074         else if (r_showsurfaces.integer == 2)
11075         {
11076                 const int *e;
11077                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11079                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11080                 {
11081                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11082                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11083                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11084                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11085                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11086                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11087                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11088                 }
11089                 R_Mesh_PrepareVertices_Generic_Unlock();
11090                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11091         }
11092         else
11093         {
11094                 int texturesurfaceindex;
11095                 int k;
11096                 const msurface_t *surface;
11097                 float surfacecolor4f[4];
11098                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11100                 vi = 0;
11101                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11102                 {
11103                         surface = texturesurfacelist[texturesurfaceindex];
11104                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11105                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11106                         for (j = 0;j < surface->num_vertices;j++)
11107                         {
11108                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11109                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11110                                 vi++;
11111                         }
11112                 }
11113                 R_Mesh_PrepareVertices_Generic_Unlock();
11114                 RSurf_DrawBatch();
11115         }
11116 }
11117
11118 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11119 {
11120         CHECKGLERROR
11121         RSurf_SetupDepthAndCulling();
11122         if (r_showsurfaces.integer)
11123         {
11124                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11125                 return;
11126         }
11127         switch (vid.renderpath)
11128         {
11129         case RENDERPATH_GL20:
11130         case RENDERPATH_D3D9:
11131         case RENDERPATH_D3D10:
11132         case RENDERPATH_D3D11:
11133         case RENDERPATH_SOFT:
11134         case RENDERPATH_GLES2:
11135                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11136                 break;
11137         case RENDERPATH_GL13:
11138         case RENDERPATH_GLES1:
11139                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11140                 break;
11141         case RENDERPATH_GL11:
11142                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11143                 break;
11144         }
11145         CHECKGLERROR
11146 }
11147
11148 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11149 {
11150         int i, j;
11151         int texturenumsurfaces, endsurface;
11152         texture_t *texture;
11153         const msurface_t *surface;
11154         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11155
11156         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11157                 RSurf_ActiveModelEntity(ent, false, false, false);
11158         else
11159         {
11160                 switch (vid.renderpath)
11161                 {
11162                 case RENDERPATH_GL20:
11163                 case RENDERPATH_D3D9:
11164                 case RENDERPATH_D3D10:
11165                 case RENDERPATH_D3D11:
11166                 case RENDERPATH_SOFT:
11167                 case RENDERPATH_GLES2:
11168                         RSurf_ActiveModelEntity(ent, true, true, false);
11169                         break;
11170                 case RENDERPATH_GL11:
11171                 case RENDERPATH_GL13:
11172                 case RENDERPATH_GLES1:
11173                         RSurf_ActiveModelEntity(ent, true, false, false);
11174                         break;
11175                 }
11176         }
11177
11178         if (r_transparentdepthmasking.integer)
11179         {
11180                 qboolean setup = false;
11181                 for (i = 0;i < numsurfaces;i = j)
11182                 {
11183                         j = i + 1;
11184                         surface = rsurface.modelsurfaces + surfacelist[i];
11185                         texture = surface->texture;
11186                         rsurface.texture = R_GetCurrentTexture(texture);
11187                         rsurface.lightmaptexture = NULL;
11188                         rsurface.deluxemaptexture = NULL;
11189                         rsurface.uselightmaptexture = false;
11190                         // scan ahead until we find a different texture
11191                         endsurface = min(i + 1024, numsurfaces);
11192                         texturenumsurfaces = 0;
11193                         texturesurfacelist[texturenumsurfaces++] = surface;
11194                         for (;j < endsurface;j++)
11195                         {
11196                                 surface = rsurface.modelsurfaces + surfacelist[j];
11197                                 if (texture != surface->texture)
11198                                         break;
11199                                 texturesurfacelist[texturenumsurfaces++] = surface;
11200                         }
11201                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11202                                 continue;
11203                         // render the range of surfaces as depth
11204                         if (!setup)
11205                         {
11206                                 setup = true;
11207                                 GL_ColorMask(0,0,0,0);
11208                                 GL_Color(1,1,1,1);
11209                                 GL_DepthTest(true);
11210                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11211                                 GL_DepthMask(true);
11212 //                              R_Mesh_ResetTextureState();
11213                         }
11214                         RSurf_SetupDepthAndCulling();
11215                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11216                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11217                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11218                         RSurf_DrawBatch();
11219                 }
11220                 if (setup)
11221                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11222         }
11223
11224         for (i = 0;i < numsurfaces;i = j)
11225         {
11226                 j = i + 1;
11227                 surface = rsurface.modelsurfaces + surfacelist[i];
11228                 texture = surface->texture;
11229                 rsurface.texture = R_GetCurrentTexture(texture);
11230                 // scan ahead until we find a different texture
11231                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11232                 texturenumsurfaces = 0;
11233                 texturesurfacelist[texturenumsurfaces++] = surface;
11234                 if(FAKELIGHT_ENABLED)
11235                 {
11236                         rsurface.lightmaptexture = NULL;
11237                         rsurface.deluxemaptexture = NULL;
11238                         rsurface.uselightmaptexture = false;
11239                         for (;j < endsurface;j++)
11240                         {
11241                                 surface = rsurface.modelsurfaces + surfacelist[j];
11242                                 if (texture != surface->texture)
11243                                         break;
11244                                 texturesurfacelist[texturenumsurfaces++] = surface;
11245                         }
11246                 }
11247                 else
11248                 {
11249                         rsurface.lightmaptexture = surface->lightmaptexture;
11250                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11251                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11252                         for (;j < endsurface;j++)
11253                         {
11254                                 surface = rsurface.modelsurfaces + surfacelist[j];
11255                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11256                                         break;
11257                                 texturesurfacelist[texturenumsurfaces++] = surface;
11258                         }
11259                 }
11260                 // render the range of surfaces
11261                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11262         }
11263         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11264 }
11265
11266 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11267 {
11268         // transparent surfaces get pushed off into the transparent queue
11269         int surfacelistindex;
11270         const msurface_t *surface;
11271         vec3_t tempcenter, center;
11272         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11273         {
11274                 surface = texturesurfacelist[surfacelistindex];
11275                 if (r_transparent_sortsurfacesbynearest.integer)
11276                 {
11277                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11278                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11279                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11280                 }
11281                 else
11282                 {
11283                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11284                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11285                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11286                 }
11287                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11288                 if (rsurface.entity->transparent_offset) // transparent offset
11289                 {
11290                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11291                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11292                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11293                 }
11294                 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11295         }
11296 }
11297
11298 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11299 {
11300         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11301                 return;
11302         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11303                 return;
11304         RSurf_SetupDepthAndCulling();
11305         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11306         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11307         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11308         RSurf_DrawBatch();
11309 }
11310
11311 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11312 {
11313         CHECKGLERROR
11314         if (depthonly)
11315                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11316         else if (prepass)
11317         {
11318                 if (!rsurface.texture->currentnumlayers)
11319                         return;
11320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11321                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11322                 else
11323                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11324         }
11325         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11326                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11327         else if (!rsurface.texture->currentnumlayers)
11328                 return;
11329         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11330         {
11331                 // in the deferred case, transparent surfaces were queued during prepass
11332                 if (!r_shadow_usingdeferredprepass)
11333                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11334         }
11335         else
11336         {
11337                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11338                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11339         }
11340         CHECKGLERROR
11341 }
11342
11343 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11344 {
11345         int i, j;
11346         texture_t *texture;
11347         R_FrameData_SetMark();
11348         // break the surface list down into batches by texture and use of lightmapping
11349         for (i = 0;i < numsurfaces;i = j)
11350         {
11351                 j = i + 1;
11352                 // texture is the base texture pointer, rsurface.texture is the
11353                 // current frame/skin the texture is directing us to use (for example
11354                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11355                 // use skin 1 instead)
11356                 texture = surfacelist[i]->texture;
11357                 rsurface.texture = R_GetCurrentTexture(texture);
11358                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11359                 {
11360                         // if this texture is not the kind we want, skip ahead to the next one
11361                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11362                                 ;
11363                         continue;
11364                 }
11365                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11366                 {
11367                         rsurface.lightmaptexture = NULL;
11368                         rsurface.deluxemaptexture = NULL;
11369                         rsurface.uselightmaptexture = false;
11370                         // simply scan ahead until we find a different texture or lightmap state
11371                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11372                                 ;
11373                 }
11374                 else
11375                 {
11376                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11377                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11378                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11379                         // simply scan ahead until we find a different texture or lightmap state
11380                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11381                                 ;
11382                 }
11383                 // render the range of surfaces
11384                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11385         }
11386         R_FrameData_ReturnToMark();
11387 }
11388
11389 float locboxvertex3f[6*4*3] =
11390 {
11391         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11392         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11393         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11394         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11395         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11396         1,0,0, 0,0,0, 0,1,0, 1,1,0
11397 };
11398
11399 unsigned short locboxelements[6*2*3] =
11400 {
11401          0, 1, 2, 0, 2, 3,
11402          4, 5, 6, 4, 6, 7,
11403          8, 9,10, 8,10,11,
11404         12,13,14, 12,14,15,
11405         16,17,18, 16,18,19,
11406         20,21,22, 20,22,23
11407 };
11408
11409 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11410 {
11411         int i, j;
11412         cl_locnode_t *loc = (cl_locnode_t *)ent;
11413         vec3_t mins, size;
11414         float vertex3f[6*4*3];
11415         CHECKGLERROR
11416         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417         GL_DepthMask(false);
11418         GL_DepthRange(0, 1);
11419         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11420         GL_DepthTest(true);
11421         GL_CullFace(GL_NONE);
11422         R_EntityMatrix(&identitymatrix);
11423
11424 //      R_Mesh_ResetTextureState();
11425
11426         i = surfacelist[0];
11427         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11428                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11429                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11430                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11431
11432         if (VectorCompare(loc->mins, loc->maxs))
11433         {
11434                 VectorSet(size, 2, 2, 2);
11435                 VectorMA(loc->mins, -0.5f, size, mins);
11436         }
11437         else
11438         {
11439                 VectorCopy(loc->mins, mins);
11440                 VectorSubtract(loc->maxs, loc->mins, size);
11441         }
11442
11443         for (i = 0;i < 6*4*3;)
11444                 for (j = 0;j < 3;j++, i++)
11445                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11446
11447         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11448         R_SetupShader_Generic_NoTexture(false, false);
11449         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11450 }
11451
11452 void R_DrawLocs(void)
11453 {
11454         int index;
11455         cl_locnode_t *loc, *nearestloc;
11456         vec3_t center;
11457         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11458         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11459         {
11460                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11461                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11462         }
11463 }
11464
11465 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11466 {
11467         if (decalsystem->decals)
11468                 Mem_Free(decalsystem->decals);
11469         memset(decalsystem, 0, sizeof(*decalsystem));
11470 }
11471
11472 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, unsigned int decalsequence)
11473 {
11474         tridecal_t *decal;
11475         tridecal_t *decals;
11476         int i;
11477
11478         // expand or initialize the system
11479         if (decalsystem->maxdecals <= decalsystem->numdecals)
11480         {
11481                 decalsystem_t old = *decalsystem;
11482                 qboolean useshortelements;
11483                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11484                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11485                 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
11486                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11487                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11488                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11489                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11490                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11491                 if (decalsystem->numdecals)
11492                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11493                 if (old.decals)
11494                         Mem_Free(old.decals);
11495                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11496                         decalsystem->element3i[i] = i;
11497                 if (useshortelements)
11498                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11499                                 decalsystem->element3s[i] = i;
11500         }
11501
11502         // grab a decal and search for another free slot for the next one
11503         decals = decalsystem->decals;
11504         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11505         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11506                 ;
11507         decalsystem->freedecal = i;
11508         if (decalsystem->numdecals <= i)
11509                 decalsystem->numdecals = i + 1;
11510
11511         // initialize the decal
11512         decal->lived = 0;
11513         decal->triangleindex = triangleindex;
11514         decal->surfaceindex = surfaceindex;
11515         decal->decalsequence = decalsequence;
11516         decal->color4f[0][0] = c0[0];
11517         decal->color4f[0][1] = c0[1];
11518         decal->color4f[0][2] = c0[2];
11519         decal->color4f[0][3] = 1;
11520         decal->color4f[1][0] = c1[0];
11521         decal->color4f[1][1] = c1[1];
11522         decal->color4f[1][2] = c1[2];
11523         decal->color4f[1][3] = 1;
11524         decal->color4f[2][0] = c2[0];
11525         decal->color4f[2][1] = c2[1];
11526         decal->color4f[2][2] = c2[2];
11527         decal->color4f[2][3] = 1;
11528         decal->vertex3f[0][0] = v0[0];
11529         decal->vertex3f[0][1] = v0[1];
11530         decal->vertex3f[0][2] = v0[2];
11531         decal->vertex3f[1][0] = v1[0];
11532         decal->vertex3f[1][1] = v1[1];
11533         decal->vertex3f[1][2] = v1[2];
11534         decal->vertex3f[2][0] = v2[0];
11535         decal->vertex3f[2][1] = v2[1];
11536         decal->vertex3f[2][2] = v2[2];
11537         decal->texcoord2f[0][0] = t0[0];
11538         decal->texcoord2f[0][1] = t0[1];
11539         decal->texcoord2f[1][0] = t1[0];
11540         decal->texcoord2f[1][1] = t1[1];
11541         decal->texcoord2f[2][0] = t2[0];
11542         decal->texcoord2f[2][1] = t2[1];
11543         TriangleNormal(v0, v1, v2, decal->plane);
11544         VectorNormalize(decal->plane);
11545         decal->plane[3] = DotProduct(v0, decal->plane);
11546 }
11547
11548 extern cvar_t cl_decals_bias;
11549 extern cvar_t cl_decals_models;
11550 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11551 // baseparms, parms, temps
11552 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11553 {
11554         int cornerindex;
11555         int index;
11556         float v[9][3];
11557         const float *vertex3f;
11558         const float *normal3f;
11559         int numpoints;
11560         float points[2][9][3];
11561         float temp[3];
11562         float tc[9][2];
11563         float f;
11564         float c[9][4];
11565         const int *e;
11566
11567         e = rsurface.modelelement3i + 3*triangleindex;
11568
11569         vertex3f = rsurface.modelvertex3f;
11570         normal3f = rsurface.modelnormal3f;
11571
11572         if (normal3f)
11573         {
11574                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11575                 {
11576                         index = 3*e[cornerindex];
11577                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11578                 }
11579         }
11580         else
11581         {
11582                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11583                 {
11584                         index = 3*e[cornerindex];
11585                         VectorCopy(vertex3f + index, v[cornerindex]);
11586                 }
11587         }
11588
11589         // cull backfaces
11590         //TriangleNormal(v[0], v[1], v[2], normal);
11591         //if (DotProduct(normal, localnormal) < 0.0f)
11592         //      continue;
11593         // clip by each of the box planes formed from the projection matrix
11594         // if anything survives, we emit the decal
11595         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11596         if (numpoints < 3)
11597                 return;
11598         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11599         if (numpoints < 3)
11600                 return;
11601         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11602         if (numpoints < 3)
11603                 return;
11604         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11605         if (numpoints < 3)
11606                 return;
11607         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11608         if (numpoints < 3)
11609                 return;
11610         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
11611         if (numpoints < 3)
11612                 return;
11613         // some part of the triangle survived, so we have to accept it...
11614         if (dynamic)
11615         {
11616                 // dynamic always uses the original triangle
11617                 numpoints = 3;
11618                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11619                 {
11620                         index = 3*e[cornerindex];
11621                         VectorCopy(vertex3f + index, v[cornerindex]);
11622                 }
11623         }
11624         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11625         {
11626                 // convert vertex positions to texcoords
11627                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11628                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11629                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11630                 // calculate distance fade from the projection origin
11631                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11632                 f = bound(0.0f, f, 1.0f);
11633                 c[cornerindex][0] = r * f;
11634                 c[cornerindex][1] = g * f;
11635                 c[cornerindex][2] = b * f;
11636                 c[cornerindex][3] = 1.0f;
11637                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11638         }
11639         if (dynamic)
11640                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
11641         else
11642                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11643                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
11644 }
11645 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11646 {
11647         matrix4x4_t projection;
11648         decalsystem_t *decalsystem;
11649         qboolean dynamic;
11650         dp_model_t *model;
11651         const msurface_t *surface;
11652         const msurface_t *surfaces;
11653         const int *surfacelist;
11654         const texture_t *texture;
11655         int numtriangles;
11656         int numsurfacelist;
11657         int surfacelistindex;
11658         int surfaceindex;
11659         int triangleindex;
11660         float localorigin[3];
11661         float localnormal[3];
11662         float localmins[3];
11663         float localmaxs[3];
11664         float localsize;
11665         //float normal[3];
11666         float planes[6][4];
11667         float angles[3];
11668         bih_t *bih;
11669         int bih_triangles_count;
11670         int bih_triangles[256];
11671         int bih_surfaces[256];
11672
11673         decalsystem = &ent->decalsystem;
11674         model = ent->model;
11675         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11676         {
11677                 R_DecalSystem_Reset(&ent->decalsystem);
11678                 return;
11679         }
11680
11681         if (!model->brush.data_leafs && !cl_decals_models.integer)
11682         {
11683                 if (decalsystem->model)
11684                         R_DecalSystem_Reset(decalsystem);
11685                 return;
11686         }
11687
11688         if (decalsystem->model != model)
11689                 R_DecalSystem_Reset(decalsystem);
11690         decalsystem->model = model;
11691
11692         RSurf_ActiveModelEntity(ent, true, false, false);
11693
11694         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11695         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11696         VectorNormalize(localnormal);
11697         localsize = worldsize*rsurface.inversematrixscale;
11698         localmins[0] = localorigin[0] - localsize;
11699         localmins[1] = localorigin[1] - localsize;
11700         localmins[2] = localorigin[2] - localsize;
11701         localmaxs[0] = localorigin[0] + localsize;
11702         localmaxs[1] = localorigin[1] + localsize;
11703         localmaxs[2] = localorigin[2] + localsize;
11704
11705         //VectorCopy(localnormal, planes[4]);
11706         //VectorVectors(planes[4], planes[2], planes[0]);
11707         AnglesFromVectors(angles, localnormal, NULL, false);
11708         AngleVectors(angles, planes[0], planes[2], planes[4]);
11709         VectorNegate(planes[0], planes[1]);
11710         VectorNegate(planes[2], planes[3]);
11711         VectorNegate(planes[4], planes[5]);
11712         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11713         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11714         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11715         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11716         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11717         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11718
11719 #if 1
11720 // works
11721 {
11722         matrix4x4_t forwardprojection;
11723         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11724         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11725 }
11726 #else
11727 // broken
11728 {
11729         float projectionvector[4][3];
11730         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11731         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11732         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11733         projectionvector[0][0] = planes[0][0] * ilocalsize;
11734         projectionvector[0][1] = planes[1][0] * ilocalsize;
11735         projectionvector[0][2] = planes[2][0] * ilocalsize;
11736         projectionvector[1][0] = planes[0][1] * ilocalsize;
11737         projectionvector[1][1] = planes[1][1] * ilocalsize;
11738         projectionvector[1][2] = planes[2][1] * ilocalsize;
11739         projectionvector[2][0] = planes[0][2] * ilocalsize;
11740         projectionvector[2][1] = planes[1][2] * ilocalsize;
11741         projectionvector[2][2] = planes[2][2] * ilocalsize;
11742         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11743         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11744         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11745         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11746 }
11747 #endif
11748
11749         dynamic = model->surfmesh.isanimated;
11750         numsurfacelist = model->nummodelsurfaces;
11751         surfacelist = model->sortedmodelsurfaces;
11752         surfaces = model->data_surfaces;
11753
11754         bih = NULL;
11755         bih_triangles_count = -1;
11756         if(!dynamic)
11757         {
11758                 if(model->render_bih.numleafs)
11759                         bih = &model->render_bih;
11760                 else if(model->collision_bih.numleafs)
11761                         bih = &model->collision_bih;
11762         }
11763         if(bih)
11764                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11765         if(bih_triangles_count == 0)
11766                 return;
11767         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11768                 return;
11769         if(bih_triangles_count > 0)
11770         {
11771                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11772                 {
11773                         surfaceindex = bih_surfaces[triangleindex];
11774                         surface = surfaces + surfaceindex;
11775                         texture = surface->texture;
11776                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11777                                 continue;
11778                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11779                                 continue;
11780                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11781                 }
11782         }
11783         else
11784         {
11785                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11786                 {
11787                         surfaceindex = surfacelist[surfacelistindex];
11788                         surface = surfaces + surfaceindex;
11789                         // check cull box first because it rejects more than any other check
11790                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11791                                 continue;
11792                         // skip transparent surfaces
11793                         texture = surface->texture;
11794                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11795                                 continue;
11796                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11797                                 continue;
11798                         numtriangles = surface->num_triangles;
11799                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11800                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11801                 }
11802         }
11803 }
11804
11805 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11806 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11807 {
11808         int renderentityindex;
11809         float worldmins[3];
11810         float worldmaxs[3];
11811         entity_render_t *ent;
11812
11813         if (!cl_decals_newsystem.integer)
11814                 return;
11815
11816         worldmins[0] = worldorigin[0] - worldsize;
11817         worldmins[1] = worldorigin[1] - worldsize;
11818         worldmins[2] = worldorigin[2] - worldsize;
11819         worldmaxs[0] = worldorigin[0] + worldsize;
11820         worldmaxs[1] = worldorigin[1] + worldsize;
11821         worldmaxs[2] = worldorigin[2] + worldsize;
11822
11823         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11824
11825         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11826         {
11827                 ent = r_refdef.scene.entities[renderentityindex];
11828                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11829                         continue;
11830
11831                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11832         }
11833 }
11834
11835 typedef struct r_decalsystem_splatqueue_s
11836 {
11837         vec3_t worldorigin;
11838         vec3_t worldnormal;
11839         float color[4];
11840         float tcrange[4];
11841         float worldsize;
11842         unsigned int decalsequence;
11843 }
11844 r_decalsystem_splatqueue_t;
11845
11846 int r_decalsystem_numqueued = 0;
11847 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11848
11849 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11850 {
11851         r_decalsystem_splatqueue_t *queue;
11852
11853         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11854                 return;
11855
11856         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11857         VectorCopy(worldorigin, queue->worldorigin);
11858         VectorCopy(worldnormal, queue->worldnormal);
11859         Vector4Set(queue->color, r, g, b, a);
11860         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11861         queue->worldsize = worldsize;
11862         queue->decalsequence = cl.decalsequence++;
11863 }
11864
11865 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11866 {
11867         int i;
11868         r_decalsystem_splatqueue_t *queue;
11869
11870         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11871                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11872         r_decalsystem_numqueued = 0;
11873 }
11874
11875 extern cvar_t cl_decals_max;
11876 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11877 {
11878         int i;
11879         decalsystem_t *decalsystem = &ent->decalsystem;
11880         int numdecals;
11881         unsigned int killsequence;
11882         tridecal_t *decal;
11883         float frametime;
11884         float lifetime;
11885
11886         if (!decalsystem->numdecals)
11887                 return;
11888
11889         if (r_showsurfaces.integer)
11890                 return;
11891
11892         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11893         {
11894                 R_DecalSystem_Reset(decalsystem);
11895                 return;
11896         }
11897
11898         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11899         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11900
11901         if (decalsystem->lastupdatetime)
11902                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11903         else
11904                 frametime = 0;
11905         decalsystem->lastupdatetime = r_refdef.scene.time;
11906         numdecals = decalsystem->numdecals;
11907
11908         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11909         {
11910                 if (decal->color4f[0][3])
11911                 {
11912                         decal->lived += frametime;
11913                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11914                         {
11915                                 memset(decal, 0, sizeof(*decal));
11916                                 if (decalsystem->freedecal > i)
11917                                         decalsystem->freedecal = i;
11918                         }
11919                 }
11920         }
11921         decal = decalsystem->decals;
11922         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11923                 numdecals--;
11924
11925         // collapse the array by shuffling the tail decals into the gaps
11926         for (;;)
11927         {
11928                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11929                         decalsystem->freedecal++;
11930                 if (decalsystem->freedecal == numdecals)
11931                         break;
11932                 decal[decalsystem->freedecal] = decal[--numdecals];
11933         }
11934
11935         decalsystem->numdecals = numdecals;
11936
11937         if (numdecals <= 0)
11938         {
11939                 // if there are no decals left, reset decalsystem
11940                 R_DecalSystem_Reset(decalsystem);
11941         }
11942 }
11943
11944 extern skinframe_t *decalskinframe;
11945 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11946 {
11947         int i;
11948         decalsystem_t *decalsystem = &ent->decalsystem;
11949         int numdecals;
11950         tridecal_t *decal;
11951         float faderate;
11952         float alpha;
11953         float *v3f;
11954         float *c4f;
11955         float *t2f;
11956         const int *e;
11957         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11958         int numtris = 0;
11959
11960         numdecals = decalsystem->numdecals;
11961         if (!numdecals)
11962                 return;
11963
11964         if (r_showsurfaces.integer)
11965                 return;
11966
11967         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11968         {
11969                 R_DecalSystem_Reset(decalsystem);
11970                 return;
11971         }
11972
11973         // if the model is static it doesn't matter what value we give for
11974         // wantnormals and wanttangents, so this logic uses only rules applicable
11975         // to a model, knowing that they are meaningless otherwise
11976         RSurf_ActiveModelEntity(ent, false, false, false);
11977
11978         decalsystem->lastupdatetime = r_refdef.scene.time;
11979
11980         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11981
11982         // update vertex positions for animated models
11983         v3f = decalsystem->vertex3f;
11984         c4f = decalsystem->color4f;
11985         t2f = decalsystem->texcoord2f;
11986         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11987         {
11988                 if (!decal->color4f[0][3])
11989                         continue;
11990
11991                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11992                         continue;
11993
11994                 // skip backfaces
11995                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11996                         continue;
11997
11998                 // update color values for fading decals
11999                 if (decal->lived >= cl_decals_time.value)
12000                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12001                 else
12002                         alpha = 1.0f;
12003
12004                 c4f[ 0] = decal->color4f[0][0] * alpha;
12005                 c4f[ 1] = decal->color4f[0][1] * alpha;
12006                 c4f[ 2] = decal->color4f[0][2] * alpha;
12007                 c4f[ 3] = 1;
12008                 c4f[ 4] = decal->color4f[1][0] * alpha;
12009                 c4f[ 5] = decal->color4f[1][1] * alpha;
12010                 c4f[ 6] = decal->color4f[1][2] * alpha;
12011                 c4f[ 7] = 1;
12012                 c4f[ 8] = decal->color4f[2][0] * alpha;
12013                 c4f[ 9] = decal->color4f[2][1] * alpha;
12014                 c4f[10] = decal->color4f[2][2] * alpha;
12015                 c4f[11] = 1;
12016
12017                 t2f[0] = decal->texcoord2f[0][0];
12018                 t2f[1] = decal->texcoord2f[0][1];
12019                 t2f[2] = decal->texcoord2f[1][0];
12020                 t2f[3] = decal->texcoord2f[1][1];
12021                 t2f[4] = decal->texcoord2f[2][0];
12022                 t2f[5] = decal->texcoord2f[2][1];
12023
12024                 // update vertex positions for animated models
12025                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12026                 {
12027                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12028                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12029                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12030                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12031                 }
12032                 else
12033                 {
12034                         VectorCopy(decal->vertex3f[0], v3f);
12035                         VectorCopy(decal->vertex3f[1], v3f + 3);
12036                         VectorCopy(decal->vertex3f[2], v3f + 6);
12037                 }
12038
12039                 if (r_refdef.fogenabled)
12040                 {
12041                         alpha = RSurf_FogVertex(v3f);
12042                         VectorScale(c4f, alpha, c4f);
12043                         alpha = RSurf_FogVertex(v3f + 3);
12044                         VectorScale(c4f + 4, alpha, c4f + 4);
12045                         alpha = RSurf_FogVertex(v3f + 6);
12046                         VectorScale(c4f + 8, alpha, c4f + 8);
12047                 }
12048
12049                 v3f += 9;
12050                 c4f += 12;
12051                 t2f += 6;
12052                 numtris++;
12053         }
12054
12055         if (numtris > 0)
12056         {
12057                 r_refdef.stats[r_stat_drawndecals] += numtris;
12058
12059                 // now render the decals all at once
12060                 // (this assumes they all use one particle font texture!)
12061                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
12062 //              R_Mesh_ResetTextureState();
12063                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12064                 GL_DepthMask(false);
12065                 GL_DepthRange(0, 1);
12066                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12067                 GL_DepthTest(true);
12068                 GL_CullFace(GL_NONE);
12069                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12070                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12071                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12072         }
12073 }
12074
12075 static void R_DrawModelDecals(void)
12076 {
12077         int i, numdecals;
12078
12079         // fade faster when there are too many decals
12080         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12081         for (i = 0;i < r_refdef.scene.numentities;i++)
12082                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12083
12084         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12085         for (i = 0;i < r_refdef.scene.numentities;i++)
12086                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12087                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12088
12089         R_DecalSystem_ApplySplatEntitiesQueue();
12090
12091         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12092         for (i = 0;i < r_refdef.scene.numentities;i++)
12093                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12094
12095         r_refdef.stats[r_stat_totaldecals] += numdecals;
12096
12097         if (r_showsurfaces.integer)
12098                 return;
12099
12100         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12101
12102         for (i = 0;i < r_refdef.scene.numentities;i++)
12103         {
12104                 if (!r_refdef.viewcache.entityvisible[i])
12105                         continue;
12106                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12107                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12108         }
12109 }
12110
12111 extern cvar_t mod_collision_bih;
12112 static void R_DrawDebugModel(void)
12113 {
12114         entity_render_t *ent = rsurface.entity;
12115         int i, j, flagsmask;
12116         const msurface_t *surface;
12117         dp_model_t *model = ent->model;
12118
12119         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12120                 return;
12121
12122         if (r_showoverdraw.value > 0)
12123         {
12124                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12125                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12126                 R_SetupShader_Generic_NoTexture(false, false);
12127                 GL_DepthTest(false);
12128                 GL_DepthMask(false);
12129                 GL_DepthRange(0, 1);
12130                 GL_BlendFunc(GL_ONE, GL_ONE);
12131                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12132                 {
12133                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12134                                 continue;
12135                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12136                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12137                         {
12138                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12139                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12140                                 if (!rsurface.texture->currentlayers->depthmask)
12141                                         GL_Color(c, 0, 0, 1.0f);
12142                                 else if (ent == r_refdef.scene.worldentity)
12143                                         GL_Color(c, c, c, 1.0f);
12144                                 else
12145                                         GL_Color(0, c, 0, 1.0f);
12146                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12147                                 RSurf_DrawBatch();
12148                         }
12149                 }
12150                 rsurface.texture = NULL;
12151         }
12152
12153         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12154
12155 //      R_Mesh_ResetTextureState();
12156         R_SetupShader_Generic_NoTexture(false, false);
12157         GL_DepthRange(0, 1);
12158         GL_DepthTest(!r_showdisabledepthtest.integer);
12159         GL_DepthMask(false);
12160         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12161
12162         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12163         {
12164                 int triangleindex;
12165                 int bihleafindex;
12166                 qboolean cullbox = false;
12167                 const q3mbrush_t *brush;
12168                 const bih_t *bih = &model->collision_bih;
12169                 const bih_leaf_t *bihleaf;
12170                 float vertex3f[3][3];
12171                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12172                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12173                 {
12174                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12175                                 continue;
12176                         switch (bihleaf->type)
12177                         {
12178                         case BIH_BRUSH:
12179                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12180                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12181                                 {
12182                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12183                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12184                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12185                                 }
12186                                 break;
12187                         case BIH_COLLISIONTRIANGLE:
12188                                 triangleindex = bihleaf->itemindex;
12189                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12190                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12191                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12192                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12193                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12194                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12195                                 break;
12196                         case BIH_RENDERTRIANGLE:
12197                                 triangleindex = bihleaf->itemindex;
12198                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12199                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12200                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12201                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12202                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12203                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12204                                 break;
12205                         }
12206                 }
12207         }
12208
12209         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12210
12211 #ifndef USE_GLES2
12212         if (r_showtris.integer && qglPolygonMode)
12213         {
12214                 if (r_showdisabledepthtest.integer)
12215                 {
12216                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12217                         GL_DepthMask(false);
12218                 }
12219                 else
12220                 {
12221                         GL_BlendFunc(GL_ONE, GL_ZERO);
12222                         GL_DepthMask(true);
12223                 }
12224                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12225                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12226                 {
12227                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12228                                 continue;
12229                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12230                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12231                         {
12232                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12233                                 if (!rsurface.texture->currentlayers->depthmask)
12234                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12235                                 else if (ent == r_refdef.scene.worldentity)
12236                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12237                                 else
12238                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12239                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12240                                 RSurf_DrawBatch();
12241                         }
12242                 }
12243                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12244                 rsurface.texture = NULL;
12245         }
12246
12247         if (r_shownormals.value != 0 && qglBegin)
12248         {
12249                 int l, k;
12250                 vec3_t v;
12251                 if (r_showdisabledepthtest.integer)
12252                 {
12253                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12254                         GL_DepthMask(false);
12255                 }
12256                 else
12257                 {
12258                         GL_BlendFunc(GL_ONE, GL_ZERO);
12259                         GL_DepthMask(true);
12260                 }
12261                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12262                 {
12263                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12264                                 continue;
12265                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12266                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12267                         {
12268                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12269                                 qglBegin(GL_LINES);
12270                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12271                                 {
12272                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12273                                         {
12274                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12275                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12276                                                 qglVertex3f(v[0], v[1], v[2]);
12277                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12278                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12279                                                 qglVertex3f(v[0], v[1], v[2]);
12280                                         }
12281                                 }
12282                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12283                                 {
12284                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12285                                         {
12286                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12287                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12288                                                 qglVertex3f(v[0], v[1], v[2]);
12289                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12290                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12291                                                 qglVertex3f(v[0], v[1], v[2]);
12292                                         }
12293                                 }
12294                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12295                                 {
12296                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12297                                         {
12298                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12299                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12300                                                 qglVertex3f(v[0], v[1], v[2]);
12301                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12302                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12303                                                 qglVertex3f(v[0], v[1], v[2]);
12304                                         }
12305                                 }
12306                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12307                                 {
12308                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12309                                         {
12310                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12311                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12312                                                 qglVertex3f(v[0], v[1], v[2]);
12313                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12314                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12315                                                 qglVertex3f(v[0], v[1], v[2]);
12316                                         }
12317                                 }
12318                                 qglEnd();
12319                                 CHECKGLERROR
12320                         }
12321                 }
12322                 rsurface.texture = NULL;
12323         }
12324 #endif
12325 }
12326
12327 int r_maxsurfacelist = 0;
12328 const msurface_t **r_surfacelist = NULL;
12329 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12330 {
12331         int i, j, endj, flagsmask;
12332         dp_model_t *model = ent->model;
12333         msurface_t *surfaces;
12334         unsigned char *update;
12335         int numsurfacelist = 0;
12336         if (model == NULL)
12337                 return;
12338
12339         if (r_maxsurfacelist < model->num_surfaces)
12340         {
12341                 r_maxsurfacelist = model->num_surfaces;
12342                 if (r_surfacelist)
12343                         Mem_Free((msurface_t **)r_surfacelist);
12344                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12345         }
12346
12347         if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12348                 RSurf_ActiveModelEntity(ent, false, false, false);
12349         else if (prepass)
12350                 RSurf_ActiveModelEntity(ent, true, true, true);
12351         else if (depthonly)
12352         {
12353                 switch (vid.renderpath)
12354                 {
12355                 case RENDERPATH_GL20:
12356                 case RENDERPATH_D3D9:
12357                 case RENDERPATH_D3D10:
12358                 case RENDERPATH_D3D11:
12359                 case RENDERPATH_SOFT:
12360                 case RENDERPATH_GLES2:
12361                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12362                         break;
12363                 case RENDERPATH_GL11:
12364                 case RENDERPATH_GL13:
12365                 case RENDERPATH_GLES1:
12366                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12367                         break;
12368                 }
12369         }
12370         else
12371         {
12372                 switch (vid.renderpath)
12373                 {
12374                 case RENDERPATH_GL20:
12375                 case RENDERPATH_D3D9:
12376                 case RENDERPATH_D3D10:
12377                 case RENDERPATH_D3D11:
12378                 case RENDERPATH_SOFT:
12379                 case RENDERPATH_GLES2:
12380                         RSurf_ActiveModelEntity(ent, true, true, false);
12381                         break;
12382                 case RENDERPATH_GL11:
12383                 case RENDERPATH_GL13:
12384                 case RENDERPATH_GLES1:
12385                         RSurf_ActiveModelEntity(ent, true, false, false);
12386                         break;
12387                 }
12388         }
12389
12390         surfaces = model->data_surfaces;
12391         update = model->brushq1.lightmapupdateflags;
12392
12393         // update light styles
12394         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12395         {
12396                 model_brush_lightstyleinfo_t *style;
12397                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12398                 {
12399                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12400                         {
12401                                 int *list = style->surfacelist;
12402                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12403                                 for (j = 0;j < style->numsurfaces;j++)
12404                                         update[list[j]] = true;
12405                         }
12406                 }
12407         }
12408
12409         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12410
12411         if (debug)
12412         {
12413                 R_DrawDebugModel();
12414                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12415                 return;
12416         }
12417
12418         rsurface.lightmaptexture = NULL;
12419         rsurface.deluxemaptexture = NULL;
12420         rsurface.uselightmaptexture = false;
12421         rsurface.texture = NULL;
12422         rsurface.rtlight = NULL;
12423         numsurfacelist = 0;
12424         // add visible surfaces to draw list
12425         if (ent == r_refdef.scene.worldentity)
12426         {
12427                 // for the world entity, check surfacevisible
12428                 for (i = 0;i < model->nummodelsurfaces;i++)
12429                 {
12430                         j = model->sortedmodelsurfaces[i];
12431                         if (r_refdef.viewcache.world_surfacevisible[j])
12432                                 r_surfacelist[numsurfacelist++] = surfaces + j;
12433                 }
12434         }
12435         else
12436         {
12437                 // add all surfaces
12438                 for (i = 0; i < model->nummodelsurfaces; i++)
12439                         r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12440         }
12441         // don't do anything if there were no surfaces
12442         if (!numsurfacelist)
12443         {
12444                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12445                 return;
12446         }
12447         // update lightmaps if needed
12448         if (update)
12449         {
12450                 int updated = 0;
12451                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12452                 {
12453                         if (update[j])
12454                         {
12455                                 updated++;
12456                                 R_BuildLightMap(ent, surfaces + j);
12457                         }
12458                 }
12459         }
12460
12461         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12462
12463         // add to stats if desired
12464         if (r_speeds.integer && !skysurfaces && !depthonly)
12465         {
12466                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12467                 for (j = 0;j < numsurfacelist;j++)
12468                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12469         }
12470
12471         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12472 }
12473
12474 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12475 {
12476         int q;
12477         static texture_t texture;
12478         static msurface_t surface;
12479         const msurface_t *surfacelist = &surface;
12480
12481         // fake enough texture and surface state to render this geometry
12482
12483         texture.update_lastrenderframe = -1; // regenerate this texture
12484         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12485         texture.basealpha = 1.0f;
12486         texture.currentskinframe = skinframe;
12487         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12488         texture.offsetmapping = OFFSETMAPPING_OFF;
12489         texture.offsetscale = 1;
12490         texture.specularscalemod = 1;
12491         texture.specularpowermod = 1;
12492         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12493         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12494         // JUST GREP FOR "specularscalemod = 1".
12495
12496         for (q = 0; q < 3; q++)
12497         {
12498                 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12499                 texture.render_modellight_lightdir[q] = q == 2;
12500                 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12501                 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12502                 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12503                 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12504                 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12505                 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12506                 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12507                 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12508         }
12509         texture.currentalpha = 1.0f;
12510
12511         surface.texture = &texture;
12512         surface.num_triangles = numtriangles;
12513         surface.num_firsttriangle = firsttriangle;
12514         surface.num_vertices = numvertices;
12515         surface.num_firstvertex = firstvertex;
12516
12517         // now render it
12518         rsurface.texture = R_GetCurrentTexture(surface.texture);
12519         rsurface.lightmaptexture = NULL;
12520         rsurface.deluxemaptexture = NULL;
12521         rsurface.uselightmaptexture = false;
12522         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12523 }
12524
12525 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12526 {
12527         static msurface_t surface;
12528         const msurface_t *surfacelist = &surface;
12529
12530         // fake enough texture and surface state to render this geometry
12531         surface.texture = texture;
12532         surface.num_triangles = numtriangles;
12533         surface.num_firsttriangle = firsttriangle;
12534         surface.num_vertices = numvertices;
12535         surface.num_firstvertex = firstvertex;
12536
12537         // now render it
12538         rsurface.texture = R_GetCurrentTexture(surface.texture);
12539         rsurface.lightmaptexture = NULL;
12540         rsurface.deluxemaptexture = NULL;
12541         rsurface.uselightmaptexture = false;
12542         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12543 }