]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Add CL_MeshEntities_*, every frame in the client all MESH_ entities are added to...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
32
33 #ifdef SUPPORTD3D
34 #include <d3d9.h>
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
36 #endif
37
38 #ifdef WIN32
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 #ifdef __cplusplus
45 }
46 #endif
47 #endif
48
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
51
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
56 qboolean r_loadfog;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
60
61 //
62 // screen size info
63 //
64 r_refdef_t r_refdef;
65
66 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
73 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
74 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
75 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
76 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
82 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
84
85 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
93 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
94 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%,  10 = 100%)" };
98 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
105 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
106 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
116 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127
128 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
129 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
130 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
131 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."};
132 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
133 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
134 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
135 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."};
136 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
137 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
138 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
139 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."};
140 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
141 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"};
142 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"};
143 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
144 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
145 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
146 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
147 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
148 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"};
149 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
150 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
151 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
152 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
153 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
154
155 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
156 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
157 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
158 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
159 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
160 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
161 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
162 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
163
164 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)"};
165 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"};
166
167 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
168 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
169 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
170
171 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"};
172 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"};
173 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"};
174 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
175 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
176 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"};
177 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)"};
178 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)"};
179 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
180
181 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
182 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)"};
183 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
184 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)"};
185 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
186 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)"};
187 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)"};
188 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
189 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"};
190 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."};
191 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199 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)"};
200
201 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)"};
202 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)"};
203 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
204 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"};
205 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
206 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
207 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
208 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"};
209 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"};
210 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)"};
211
212 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
213 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
214 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
215 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
216
217 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
218 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
219
220 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
221 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
222 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
223 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
224 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
225 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
226
227 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
228 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
229 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
230 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
231 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
232 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
233 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
234 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
235 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
236 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
237
238 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"};
239
240 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"};
241
242 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
243
244 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
245
246 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)"};
247 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)"};
248 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
249 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
250
251 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
252 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"};
253
254 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."};
255
256 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)"};
257 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
258 {
259         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
260         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
261         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
262         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
263 };
264
265 extern cvar_t v_glslgamma;
266 extern cvar_t v_glslgamma_2d;
267
268 extern qboolean v_flipped_state;
269
270 r_framebufferstate_t r_fb;
271
272 /// shadow volume bsp struct with automatically growing nodes buffer
273 svbsp_t r_svbsp;
274
275 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
276
277 rtexture_t *r_texture_blanknormalmap;
278 rtexture_t *r_texture_white;
279 rtexture_t *r_texture_grey128;
280 rtexture_t *r_texture_black;
281 rtexture_t *r_texture_notexture;
282 rtexture_t *r_texture_whitecube;
283 rtexture_t *r_texture_normalizationcube;
284 rtexture_t *r_texture_fogattenuation;
285 rtexture_t *r_texture_fogheighttexture;
286 rtexture_t *r_texture_gammaramps;
287 unsigned int r_texture_gammaramps_serial;
288 //rtexture_t *r_texture_fogintensity;
289 rtexture_t *r_texture_reflectcube;
290
291 // TODO: hash lookups?
292 typedef struct cubemapinfo_s
293 {
294         char basename[64];
295         rtexture_t *texture;
296 }
297 cubemapinfo_t;
298
299 int r_texture_numcubemaps;
300 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
301
302 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
303 unsigned int r_numqueries;
304 unsigned int r_maxqueries;
305
306 typedef struct r_qwskincache_s
307 {
308         char name[MAX_QPATH];
309         skinframe_t *skinframe;
310 }
311 r_qwskincache_t;
312
313 static r_qwskincache_t *r_qwskincache;
314 static int r_qwskincache_size;
315
316 /// vertex coordinates for a quad that covers the screen exactly
317 extern const float r_screenvertex3f[12];
318 extern const float r_d3dscreenvertex3f[12];
319 const float r_screenvertex3f[12] =
320 {
321         0, 0, 0,
322         1, 0, 0,
323         1, 1, 0,
324         0, 1, 0
325 };
326 const float r_d3dscreenvertex3f[12] =
327 {
328         0, 1, 0,
329         1, 1, 0,
330         1, 0, 0,
331         0, 0, 0
332 };
333
334 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
335 {
336         int i;
337         for (i = 0;i < verts;i++)
338         {
339                 out[0] = in[0] * r;
340                 out[1] = in[1] * g;
341                 out[2] = in[2] * b;
342                 out[3] = in[3];
343                 in += 4;
344                 out += 4;
345         }
346 }
347
348 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
349 {
350         int i;
351         for (i = 0;i < verts;i++)
352         {
353                 out[0] = r;
354                 out[1] = g;
355                 out[2] = b;
356                 out[3] = a;
357                 out += 4;
358         }
359 }
360
361 // FIXME: move this to client?
362 void FOG_clear(void)
363 {
364         if (gamemode == GAME_NEHAHRA)
365         {
366                 Cvar_Set("gl_fogenable", "0");
367                 Cvar_Set("gl_fogdensity", "0.2");
368                 Cvar_Set("gl_fogred", "0.3");
369                 Cvar_Set("gl_foggreen", "0.3");
370                 Cvar_Set("gl_fogblue", "0.3");
371         }
372         r_refdef.fog_density = 0;
373         r_refdef.fog_red = 0;
374         r_refdef.fog_green = 0;
375         r_refdef.fog_blue = 0;
376         r_refdef.fog_alpha = 1;
377         r_refdef.fog_start = 0;
378         r_refdef.fog_end = 16384;
379         r_refdef.fog_height = 1<<30;
380         r_refdef.fog_fadedepth = 128;
381         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
382 }
383
384 static void R_BuildBlankTextures(void)
385 {
386         unsigned char data[4];
387         data[2] = 128; // normal X
388         data[1] = 128; // normal Y
389         data[0] = 255; // normal Z
390         data[3] = 255; // height
391         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392         data[0] = 255;
393         data[1] = 255;
394         data[2] = 255;
395         data[3] = 255;
396         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397         data[0] = 128;
398         data[1] = 128;
399         data[2] = 128;
400         data[3] = 255;
401         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402         data[0] = 0;
403         data[1] = 0;
404         data[2] = 0;
405         data[3] = 255;
406         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildNoTexture(void)
410 {
411         int x, y;
412         unsigned char pix[16][16][4];
413         // this makes a light grey/dark grey checkerboard texture
414         for (y = 0;y < 16;y++)
415         {
416                 for (x = 0;x < 16;x++)
417                 {
418                         if ((y < 8) ^ (x < 8))
419                         {
420                                 pix[y][x][0] = 128;
421                                 pix[y][x][1] = 128;
422                                 pix[y][x][2] = 128;
423                                 pix[y][x][3] = 255;
424                         }
425                         else
426                         {
427                                 pix[y][x][0] = 64;
428                                 pix[y][x][1] = 64;
429                                 pix[y][x][2] = 64;
430                                 pix[y][x][3] = 255;
431                         }
432                 }
433         }
434         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
435 }
436
437 static void R_BuildWhiteCube(void)
438 {
439         unsigned char data[6*1*1*4];
440         memset(data, 255, sizeof(data));
441         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
442 }
443
444 static void R_BuildNormalizationCube(void)
445 {
446         int x, y, side;
447         vec3_t v;
448         vec_t s, t, intensity;
449 #define NORMSIZE 64
450         unsigned char *data;
451         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
452         for (side = 0;side < 6;side++)
453         {
454                 for (y = 0;y < NORMSIZE;y++)
455                 {
456                         for (x = 0;x < NORMSIZE;x++)
457                         {
458                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
460                                 switch(side)
461                                 {
462                                 default:
463                                 case 0:
464                                         v[0] = 1;
465                                         v[1] = -t;
466                                         v[2] = -s;
467                                         break;
468                                 case 1:
469                                         v[0] = -1;
470                                         v[1] = -t;
471                                         v[2] = s;
472                                         break;
473                                 case 2:
474                                         v[0] = s;
475                                         v[1] = 1;
476                                         v[2] = t;
477                                         break;
478                                 case 3:
479                                         v[0] = s;
480                                         v[1] = -1;
481                                         v[2] = -t;
482                                         break;
483                                 case 4:
484                                         v[0] = s;
485                                         v[1] = -t;
486                                         v[2] = 1;
487                                         break;
488                                 case 5:
489                                         v[0] = -s;
490                                         v[1] = -t;
491                                         v[2] = -1;
492                                         break;
493                                 }
494                                 intensity = 127.0f / sqrt(DotProduct(v, v));
495                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
496                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
497                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
498                                 data[((side*64+y)*64+x)*4+3] = 255;
499                         }
500                 }
501         }
502         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
503         Mem_Free(data);
504 }
505
506 static void R_BuildFogTexture(void)
507 {
508         int x, b;
509 #define FOGWIDTH 256
510         unsigned char data1[FOGWIDTH][4];
511         //unsigned char data2[FOGWIDTH][4];
512         double d, r, alpha;
513
514         r_refdef.fogmasktable_start = r_refdef.fog_start;
515         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
516         r_refdef.fogmasktable_range = r_refdef.fogrange;
517         r_refdef.fogmasktable_density = r_refdef.fog_density;
518
519         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
520         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
521         {
522                 d = (x * r - r_refdef.fogmasktable_start);
523                 if(developer_extra.integer)
524                         Con_DPrintf("%f ", d);
525                 d = max(0, d);
526                 if (r_fog_exp2.integer)
527                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
528                 else
529                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
530                 if(developer_extra.integer)
531                         Con_DPrintf(" : %f ", alpha);
532                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
533                 if(developer_extra.integer)
534                         Con_DPrintf(" = %f\n", alpha);
535                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
536         }
537
538         for (x = 0;x < FOGWIDTH;x++)
539         {
540                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541                 data1[x][0] = b;
542                 data1[x][1] = b;
543                 data1[x][2] = b;
544                 data1[x][3] = 255;
545                 //data2[x][0] = 255 - b;
546                 //data2[x][1] = 255 - b;
547                 //data2[x][2] = 255 - b;
548                 //data2[x][3] = 255;
549         }
550         if (r_texture_fogattenuation)
551         {
552                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
554         }
555         else
556         {
557                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
558                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
559         }
560 }
561
562 static void R_BuildFogHeightTexture(void)
563 {
564         unsigned char *inpixels;
565         int size;
566         int x;
567         int y;
568         int j;
569         float c[4];
570         float f;
571         inpixels = NULL;
572         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
573         if (r_refdef.fogheighttexturename[0])
574                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
575         if (!inpixels)
576         {
577                 r_refdef.fog_height_tablesize = 0;
578                 if (r_texture_fogheighttexture)
579                         R_FreeTexture(r_texture_fogheighttexture);
580                 r_texture_fogheighttexture = NULL;
581                 if (r_refdef.fog_height_table2d)
582                         Mem_Free(r_refdef.fog_height_table2d);
583                 r_refdef.fog_height_table2d = NULL;
584                 if (r_refdef.fog_height_table1d)
585                         Mem_Free(r_refdef.fog_height_table1d);
586                 r_refdef.fog_height_table1d = NULL;
587                 return;
588         }
589         size = image_width;
590         r_refdef.fog_height_tablesize = size;
591         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
592         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
593         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
594         Mem_Free(inpixels);
595         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
596         // average fog color table accounting for every fog layer between a point
597         // and the camera.  (Note: attenuation is handled separately!)
598         for (y = 0;y < size;y++)
599         {
600                 for (x = 0;x < size;x++)
601                 {
602                         Vector4Clear(c);
603                         f = 0;
604                         if (x < y)
605                         {
606                                 for (j = x;j <= y;j++)
607                                 {
608                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609                                         f++;
610                                 }
611                         }
612                         else
613                         {
614                                 for (j = x;j >= y;j--)
615                                 {
616                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617                                         f++;
618                                 }
619                         }
620                         f = 1.0f / f;
621                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
622                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
623                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
624                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
625                 }
626         }
627         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
628 }
629
630 //=======================================================================================================================================================
631
632 static const char *builtinshaderstrings[] =
633 {
634 #include "shader_glsl.h"
635 0
636 };
637
638 const char *builtinhlslshaderstrings[] =
639 {
640 #include "shader_hlsl.h"
641 0
642 };
643
644 //=======================================================================================================================================================
645
646 typedef struct shaderpermutationinfo_s
647 {
648         const char *pretext;
649         const char *name;
650 }
651 shaderpermutationinfo_t;
652
653 typedef struct shadermodeinfo_s
654 {
655         const char *sourcebasename;
656         const char *extension;
657         const char **builtinshaderstrings;
658         const char *pretext;
659         const char *name;
660         char *filename;
661         char *builtinstring;
662         int builtincrc;
663 }
664 shadermodeinfo_t;
665
666 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
667 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
668 {
669         {"#define USEDIFFUSE\n", " diffuse"},
670         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
671         {"#define USEVIEWTINT\n", " viewtint"},
672         {"#define USECOLORMAPPING\n", " colormapping"},
673         {"#define USESATURATION\n", " saturation"},
674         {"#define USEFOGINSIDE\n", " foginside"},
675         {"#define USEFOGOUTSIDE\n", " fogoutside"},
676         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
677         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
678         {"#define USEGAMMARAMPS\n", " gammaramps"},
679         {"#define USECUBEFILTER\n", " cubefilter"},
680         {"#define USEGLOW\n", " glow"},
681         {"#define USEBLOOM\n", " bloom"},
682         {"#define USESPECULAR\n", " specular"},
683         {"#define USEPOSTPROCESSING\n", " postprocessing"},
684         {"#define USEREFLECTION\n", " reflection"},
685         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
686         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
687         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
688         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
689         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
690         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
691         {"#define USEALPHAKILL\n", " alphakill"},
692         {"#define USEREFLECTCUBE\n", " reflectcube"},
693         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
694         {"#define USEBOUNCEGRID\n", " bouncegrid"},
695         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
696         {"#define USETRIPPY\n", " trippy"},
697         {"#define USEDEPTHRGB\n", " depthrgb"},
698         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
699         {"#define USESKELETAL\n", " skeletal"},
700         {"#define USEOCCLUDE\n", " occlude"}
701 };
702
703 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
704 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
705 {
706         // SHADERLANGUAGE_GLSL
707         {
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
721                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
722                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
723                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725         },
726         // SHADERLANGUAGE_HLSL
727         {
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
741                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
742                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
743                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
744                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
745         },
746 };
747
748 struct r_glsl_permutation_s;
749 typedef struct r_glsl_permutation_s
750 {
751         /// hash lookup data
752         struct r_glsl_permutation_s *hashnext;
753         unsigned int mode;
754         unsigned int permutation;
755
756         /// indicates if we have tried compiling this permutation already
757         qboolean compiled;
758         /// 0 if compilation failed
759         int program;
760         // texture units assigned to each detected uniform
761         int tex_Texture_First;
762         int tex_Texture_Second;
763         int tex_Texture_GammaRamps;
764         int tex_Texture_Normal;
765         int tex_Texture_Color;
766         int tex_Texture_Gloss;
767         int tex_Texture_Glow;
768         int tex_Texture_SecondaryNormal;
769         int tex_Texture_SecondaryColor;
770         int tex_Texture_SecondaryGloss;
771         int tex_Texture_SecondaryGlow;
772         int tex_Texture_Pants;
773         int tex_Texture_Shirt;
774         int tex_Texture_FogHeightTexture;
775         int tex_Texture_FogMask;
776         int tex_Texture_Lightmap;
777         int tex_Texture_Deluxemap;
778         int tex_Texture_Attenuation;
779         int tex_Texture_Cube;
780         int tex_Texture_Refraction;
781         int tex_Texture_Reflection;
782         int tex_Texture_ShadowMap2D;
783         int tex_Texture_CubeProjection;
784         int tex_Texture_ScreenNormalMap;
785         int tex_Texture_ScreenDiffuse;
786         int tex_Texture_ScreenSpecular;
787         int tex_Texture_ReflectMask;
788         int tex_Texture_ReflectCube;
789         int tex_Texture_BounceGrid;
790         /// locations of detected uniforms in program object, or -1 if not found
791         int loc_Texture_First;
792         int loc_Texture_Second;
793         int loc_Texture_GammaRamps;
794         int loc_Texture_Normal;
795         int loc_Texture_Color;
796         int loc_Texture_Gloss;
797         int loc_Texture_Glow;
798         int loc_Texture_SecondaryNormal;
799         int loc_Texture_SecondaryColor;
800         int loc_Texture_SecondaryGloss;
801         int loc_Texture_SecondaryGlow;
802         int loc_Texture_Pants;
803         int loc_Texture_Shirt;
804         int loc_Texture_FogHeightTexture;
805         int loc_Texture_FogMask;
806         int loc_Texture_Lightmap;
807         int loc_Texture_Deluxemap;
808         int loc_Texture_Attenuation;
809         int loc_Texture_Cube;
810         int loc_Texture_Refraction;
811         int loc_Texture_Reflection;
812         int loc_Texture_ShadowMap2D;
813         int loc_Texture_CubeProjection;
814         int loc_Texture_ScreenNormalMap;
815         int loc_Texture_ScreenDiffuse;
816         int loc_Texture_ScreenSpecular;
817         int loc_Texture_ReflectMask;
818         int loc_Texture_ReflectCube;
819         int loc_Texture_BounceGrid;
820         int loc_Alpha;
821         int loc_BloomBlur_Parameters;
822         int loc_ClientTime;
823         int loc_Color_Ambient;
824         int loc_Color_Diffuse;
825         int loc_Color_Specular;
826         int loc_Color_Glow;
827         int loc_Color_Pants;
828         int loc_Color_Shirt;
829         int loc_DeferredColor_Ambient;
830         int loc_DeferredColor_Diffuse;
831         int loc_DeferredColor_Specular;
832         int loc_DeferredMod_Diffuse;
833         int loc_DeferredMod_Specular;
834         int loc_DistortScaleRefractReflect;
835         int loc_EyePosition;
836         int loc_FogColor;
837         int loc_FogHeightFade;
838         int loc_FogPlane;
839         int loc_FogPlaneViewDist;
840         int loc_FogRangeRecip;
841         int loc_LightColor;
842         int loc_LightDir;
843         int loc_LightPosition;
844         int loc_OffsetMapping_ScaleSteps;
845         int loc_OffsetMapping_LodDistance;
846         int loc_OffsetMapping_Bias;
847         int loc_PixelSize;
848         int loc_ReflectColor;
849         int loc_ReflectFactor;
850         int loc_ReflectOffset;
851         int loc_RefractColor;
852         int loc_Saturation;
853         int loc_ScreenCenterRefractReflect;
854         int loc_ScreenScaleRefractReflect;
855         int loc_ScreenToDepth;
856         int loc_ShadowMap_Parameters;
857         int loc_ShadowMap_TextureScale;
858         int loc_SpecularPower;
859         int loc_Skeletal_Transform12;
860         int loc_UserVec1;
861         int loc_UserVec2;
862         int loc_UserVec3;
863         int loc_UserVec4;
864         int loc_ViewTintColor;
865         int loc_ViewToLight;
866         int loc_ModelToLight;
867         int loc_TexMatrix;
868         int loc_BackgroundTexMatrix;
869         int loc_ModelViewProjectionMatrix;
870         int loc_ModelViewMatrix;
871         int loc_PixelToScreenTexCoord;
872         int loc_ModelToReflectCube;
873         int loc_ShadowMapMatrix;
874         int loc_BloomColorSubtract;
875         int loc_NormalmapScrollBlend;
876         int loc_BounceGridMatrix;
877         int loc_BounceGridIntensity;
878         /// uniform block bindings
879         int ubibind_Skeletal_Transform12_UniformBlock;
880         /// uniform block indices
881         int ubiloc_Skeletal_Transform12_UniformBlock;
882 }
883 r_glsl_permutation_t;
884
885 #define SHADERPERMUTATION_HASHSIZE 256
886
887
888 // non-degradable "lightweight" shader parameters to keep the permutations simpler
889 // these can NOT degrade! only use for simple stuff
890 enum
891 {
892         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
893         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
894         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
895         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
896         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
897         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
898         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
899         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
900         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
901         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
902         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
903         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
904         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
905         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
906 };
907 #define SHADERSTATICPARMS_COUNT 14
908
909 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
910 static int shaderstaticparms_count = 0;
911
912 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
913 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
914
915 extern qboolean r_shadow_shadowmapsampler;
916 extern int r_shadow_shadowmappcf;
917 qboolean R_CompileShader_CheckStaticParms(void)
918 {
919         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
920         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
921         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
922
923         // detect all
924         if (r_glsl_saturation_redcompensate.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
926         if (r_glsl_vertextextureblend_usebothalphas.integer)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
928         if (r_shadow_glossexact.integer)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
930         if (r_glsl_postprocess.integer)
931         {
932                 if (r_glsl_postprocess_uservec1_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
934                 if (r_glsl_postprocess_uservec2_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
936                 if (r_glsl_postprocess_uservec3_enable.integer)
937                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
938                 if (r_glsl_postprocess_uservec4_enable.integer)
939                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
940         }
941         if (r_fxaa.integer)
942                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
943         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
944                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
945
946         if (r_shadow_shadowmapsampler)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
948         if (r_shadow_shadowmappcf > 1)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
950         else if (r_shadow_shadowmappcf)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
952         if (r_celshading.integer)
953                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
954         if (r_celoutlines.integer)
955                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
956
957         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
958 }
959
960 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
961         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
962                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
963         else \
964                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
965 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
966 {
967         shaderstaticparms_count = 0;
968
969         // emit all
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
980         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
981         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
982         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
983         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
984 }
985
986 /// information about each possible shader permutation
987 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
988 /// currently selected permutation
989 r_glsl_permutation_t *r_glsl_permutation;
990 /// storage for permutations linked in the hash table
991 memexpandablearray_t r_glsl_permutationarray;
992
993 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
994 {
995         //unsigned int hashdepth = 0;
996         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
997         r_glsl_permutation_t *p;
998         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
999         {
1000                 if (p->mode == mode && p->permutation == permutation)
1001                 {
1002                         //if (hashdepth > 10)
1003                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1004                         return p;
1005                 }
1006                 //hashdepth++;
1007         }
1008         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1009         p->mode = mode;
1010         p->permutation = permutation;
1011         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1012         r_glsl_permutationhash[mode][hashindex] = p;
1013         //if (hashdepth > 10)
1014         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1015         return p;
1016 }
1017
1018 static char *R_ShaderStrCat(const char **strings)
1019 {
1020         char *string, *s;
1021         const char **p = strings;
1022         const char *t;
1023         size_t len = 0;
1024         for (p = strings;(t = *p);p++)
1025                 len += strlen(t);
1026         len++;
1027         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1028         len = 0;
1029         for (p = strings;(t = *p);p++)
1030         {
1031                 len = strlen(t);
1032                 memcpy(s, t, len);
1033                 s += len;
1034         }
1035         *s = 0;
1036         return string;
1037 }
1038
1039 static char *R_ShaderStrCat(const char **strings);
1040 static void R_InitShaderModeInfo(void)
1041 {
1042         int i, language;
1043         shadermodeinfo_t *modeinfo;
1044         // 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)
1045         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1046         {
1047                 for (i = 0; i < SHADERMODE_COUNT; i++)
1048                 {
1049                         char filename[MAX_QPATH];
1050                         modeinfo = &shadermodeinfo[language][i];
1051                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1052                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1053                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1054                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1055                 }
1056         }
1057 }
1058
1059 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1060 {
1061         char *shaderstring;
1062         // if the mode has no filename we have to return the builtin string
1063         if (builtinonly || !modeinfo->filename)
1064                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1065         // note that FS_LoadFile appends a 0 byte to make it a valid string
1066         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1067         if (shaderstring)
1068         {
1069                 if (printfromdisknotice)
1070                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1071                 return shaderstring;
1072         }
1073         // fall back to builtinstring
1074         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1075 }
1076
1077 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1078 {
1079         int i;
1080         int ubibind;
1081         int sampler;
1082         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1083         char *sourcestring;
1084         char permutationname[256];
1085         int vertstrings_count = 0;
1086         int geomstrings_count = 0;
1087         int fragstrings_count = 0;
1088         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091
1092         if (p->compiled)
1093                 return;
1094         p->compiled = true;
1095         p->program = 0;
1096
1097         permutationname[0] = 0;
1098         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1099
1100         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1101
1102         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1103         if(vid.support.glshaderversion >= 140)
1104         {
1105                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1106                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1107                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1108                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1109                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1110                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1111         }
1112         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1113         else if(vid.support.glshaderversion >= 130)
1114         {
1115                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1116                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1117                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1118                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1119                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1120                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1121         }
1122         // if we can do #version 120, we should (this adds the invariant keyword)
1123         else if(vid.support.glshaderversion >= 120)
1124         {
1125                 vertstrings_list[vertstrings_count++] = "#version 120\n";
1126                 geomstrings_list[geomstrings_count++] = "#version 120\n";
1127                 fragstrings_list[fragstrings_count++] = "#version 120\n";
1128                 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1129                 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1130                 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1131         }
1132         // GLES also adds several things from GLSL120
1133         switch(vid.renderpath)
1134         {
1135         case RENDERPATH_GLES2:
1136                 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1137                 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1138                 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1139                 break;
1140         default:
1141                 break;
1142         }
1143
1144         // the first pretext is which type of shader to compile as
1145         // (later these will all be bound together as a program object)
1146         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1147         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1148         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1149
1150         // the second pretext is the mode (for example a light source)
1151         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1152         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1153         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1154         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1155
1156         // now add all the permutation pretexts
1157         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1158         {
1159                 if (permutation & (1<<i))
1160                 {
1161                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1162                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1163                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1164                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1165                 }
1166                 else
1167                 {
1168                         // keep line numbers correct
1169                         vertstrings_list[vertstrings_count++] = "\n";
1170                         geomstrings_list[geomstrings_count++] = "\n";
1171                         fragstrings_list[fragstrings_count++] = "\n";
1172                 }
1173         }
1174
1175         // add static parms
1176         R_CompileShader_AddStaticParms(mode, permutation);
1177         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178         vertstrings_count += shaderstaticparms_count;
1179         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180         geomstrings_count += shaderstaticparms_count;
1181         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182         fragstrings_count += shaderstaticparms_count;
1183
1184         // now append the shader text itself
1185         vertstrings_list[vertstrings_count++] = sourcestring;
1186         geomstrings_list[geomstrings_count++] = sourcestring;
1187         fragstrings_list[fragstrings_count++] = sourcestring;
1188
1189         // compile the shader program
1190         if (vertstrings_count + geomstrings_count + fragstrings_count)
1191                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1192         if (p->program)
1193         {
1194                 CHECKGLERROR
1195                 qglUseProgram(p->program);CHECKGLERROR
1196                 // look up all the uniform variable names we care about, so we don't
1197                 // have to look them up every time we set them
1198
1199 #if 0
1200                 // debugging aid
1201                 {
1202                         GLint activeuniformindex = 0;
1203                         GLint numactiveuniforms = 0;
1204                         char uniformname[128];
1205                         GLsizei uniformnamelength = 0;
1206                         GLint uniformsize = 0;
1207                         GLenum uniformtype = 0;
1208                         memset(uniformname, 0, sizeof(uniformname));
1209                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1210                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1211                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1212                         {
1213                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1214                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1215                         }
1216                 }
1217 #endif
1218
1219                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1220                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1221                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1222                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1223                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1224                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1225                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1226                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1227                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1228                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1229                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1230                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1231                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1232                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1233                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1234                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1235                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1236                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1237                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1238                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1239                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1240                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1241                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1242                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1243                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1244                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1245                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1246                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1247                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1248                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1249                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1250                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1251                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1252                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1253                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1254                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1255                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1256                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1257                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1258                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1259                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1260                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1261                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1262                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1263                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1264                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1265                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1266                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1267                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1268                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1269                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1270                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1271                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1272                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1273                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1274                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1275                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1276                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1277                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1278                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1279                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1280                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1281                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1282                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1283                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1284                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1285                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1286                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1287                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1288                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1289                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1290                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1291                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1292                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1293                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1294                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1295                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1296                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1297                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1298                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1299                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1300                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1301                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1302                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1303                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1304                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1305                 // initialize the samplers to refer to the texture units we use
1306                 p->tex_Texture_First = -1;
1307                 p->tex_Texture_Second = -1;
1308                 p->tex_Texture_GammaRamps = -1;
1309                 p->tex_Texture_Normal = -1;
1310                 p->tex_Texture_Color = -1;
1311                 p->tex_Texture_Gloss = -1;
1312                 p->tex_Texture_Glow = -1;
1313                 p->tex_Texture_SecondaryNormal = -1;
1314                 p->tex_Texture_SecondaryColor = -1;
1315                 p->tex_Texture_SecondaryGloss = -1;
1316                 p->tex_Texture_SecondaryGlow = -1;
1317                 p->tex_Texture_Pants = -1;
1318                 p->tex_Texture_Shirt = -1;
1319                 p->tex_Texture_FogHeightTexture = -1;
1320                 p->tex_Texture_FogMask = -1;
1321                 p->tex_Texture_Lightmap = -1;
1322                 p->tex_Texture_Deluxemap = -1;
1323                 p->tex_Texture_Attenuation = -1;
1324                 p->tex_Texture_Cube = -1;
1325                 p->tex_Texture_Refraction = -1;
1326                 p->tex_Texture_Reflection = -1;
1327                 p->tex_Texture_ShadowMap2D = -1;
1328                 p->tex_Texture_CubeProjection = -1;
1329                 p->tex_Texture_ScreenNormalMap = -1;
1330                 p->tex_Texture_ScreenDiffuse = -1;
1331                 p->tex_Texture_ScreenSpecular = -1;
1332                 p->tex_Texture_ReflectMask = -1;
1333                 p->tex_Texture_ReflectCube = -1;
1334                 p->tex_Texture_BounceGrid = -1;
1335                 // bind the texture samplers in use
1336                 sampler = 0;
1337                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1338                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1339                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1340                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1341                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1342                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1343                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1344                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1345                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1346                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1347                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1348                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1349                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1350                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1351                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1352                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1353                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1354                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1355                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1356                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1357                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1358                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1359                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1360                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1361                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1362                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1363                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1364                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1365                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1366                 // get the uniform block indices so we can bind them
1367 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1368                 if (vid.support.arb_uniform_buffer_object)
1369                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1370                 else
1371 #endif
1372                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1373                 // clear the uniform block bindings
1374                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1375                 // bind the uniform blocks in use
1376                 ubibind = 0;
1377 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1378                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1379 #endif
1380                 // we're done compiling and setting up the shader, at least until it is used
1381                 CHECKGLERROR
1382                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1383         }
1384         else
1385                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1386
1387         // free the strings
1388         if (sourcestring)
1389                 Mem_Free(sourcestring);
1390 }
1391
1392 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1393 {
1394         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1395         if (r_glsl_permutation != perm)
1396         {
1397                 r_glsl_permutation = perm;
1398                 if (!r_glsl_permutation->program)
1399                 {
1400                         if (!r_glsl_permutation->compiled)
1401                         {
1402                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1403                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1404                         }
1405                         if (!r_glsl_permutation->program)
1406                         {
1407                                 // remove features until we find a valid permutation
1408                                 int i;
1409                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1410                                 {
1411                                         // reduce i more quickly whenever it would not remove any bits
1412                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1413                                         if (!(permutation & j))
1414                                                 continue;
1415                                         permutation -= j;
1416                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1417                                         if (!r_glsl_permutation->compiled)
1418                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1419                                         if (r_glsl_permutation->program)
1420                                                 break;
1421                                 }
1422                                 if (i >= SHADERPERMUTATION_COUNT)
1423                                 {
1424                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1425                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1426                                         qglUseProgram(0);CHECKGLERROR
1427                                         return; // no bit left to clear, entire mode is broken
1428                                 }
1429                         }
1430                 }
1431                 CHECKGLERROR
1432                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1433         }
1434         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1435         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1436         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1437         CHECKGLERROR
1438 }
1439
1440 #ifdef SUPPORTD3D
1441
1442 #ifdef SUPPORTD3D
1443 #include <d3d9.h>
1444 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1445 extern D3DCAPS9 vid_d3d9caps;
1446 #endif
1447
1448 struct r_hlsl_permutation_s;
1449 typedef struct r_hlsl_permutation_s
1450 {
1451         /// hash lookup data
1452         struct r_hlsl_permutation_s *hashnext;
1453         unsigned int mode;
1454         unsigned int permutation;
1455
1456         /// indicates if we have tried compiling this permutation already
1457         qboolean compiled;
1458         /// NULL if compilation failed
1459         IDirect3DVertexShader9 *vertexshader;
1460         IDirect3DPixelShader9 *pixelshader;
1461 }
1462 r_hlsl_permutation_t;
1463
1464 typedef enum D3DVSREGISTER_e
1465 {
1466         D3DVSREGISTER_TexMatrix = 0, // float4x4
1467         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1468         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1469         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1470         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1471         D3DVSREGISTER_ModelToLight = 20, // float4x4
1472         D3DVSREGISTER_EyePosition = 24,
1473         D3DVSREGISTER_FogPlane = 25,
1474         D3DVSREGISTER_LightDir = 26,
1475         D3DVSREGISTER_LightPosition = 27,
1476 }
1477 D3DVSREGISTER_t;
1478
1479 typedef enum D3DPSREGISTER_e
1480 {
1481         D3DPSREGISTER_Alpha = 0,
1482         D3DPSREGISTER_BloomBlur_Parameters = 1,
1483         D3DPSREGISTER_ClientTime = 2,
1484         D3DPSREGISTER_Color_Ambient = 3,
1485         D3DPSREGISTER_Color_Diffuse = 4,
1486         D3DPSREGISTER_Color_Specular = 5,
1487         D3DPSREGISTER_Color_Glow = 6,
1488         D3DPSREGISTER_Color_Pants = 7,
1489         D3DPSREGISTER_Color_Shirt = 8,
1490         D3DPSREGISTER_DeferredColor_Ambient = 9,
1491         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1492         D3DPSREGISTER_DeferredColor_Specular = 11,
1493         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1494         D3DPSREGISTER_DeferredMod_Specular = 13,
1495         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1496         D3DPSREGISTER_EyePosition = 15, // unused
1497         D3DPSREGISTER_FogColor = 16,
1498         D3DPSREGISTER_FogHeightFade = 17,
1499         D3DPSREGISTER_FogPlane = 18,
1500         D3DPSREGISTER_FogPlaneViewDist = 19,
1501         D3DPSREGISTER_FogRangeRecip = 20,
1502         D3DPSREGISTER_LightColor = 21,
1503         D3DPSREGISTER_LightDir = 22, // unused
1504         D3DPSREGISTER_LightPosition = 23,
1505         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1506         D3DPSREGISTER_PixelSize = 25,
1507         D3DPSREGISTER_ReflectColor = 26,
1508         D3DPSREGISTER_ReflectFactor = 27,
1509         D3DPSREGISTER_ReflectOffset = 28,
1510         D3DPSREGISTER_RefractColor = 29,
1511         D3DPSREGISTER_Saturation = 30,
1512         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1513         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1514         D3DPSREGISTER_ScreenToDepth = 33,
1515         D3DPSREGISTER_ShadowMap_Parameters = 34,
1516         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1517         D3DPSREGISTER_SpecularPower = 36,
1518         D3DPSREGISTER_UserVec1 = 37,
1519         D3DPSREGISTER_UserVec2 = 38,
1520         D3DPSREGISTER_UserVec3 = 39,
1521         D3DPSREGISTER_UserVec4 = 40,
1522         D3DPSREGISTER_ViewTintColor = 41,
1523         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1524         D3DPSREGISTER_BloomColorSubtract = 43,
1525         D3DPSREGISTER_ViewToLight = 44, // float4x4
1526         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1527         D3DPSREGISTER_NormalmapScrollBlend = 52,
1528         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1529         D3DPSREGISTER_OffsetMapping_Bias = 54,
1530         // next at 54
1531 }
1532 D3DPSREGISTER_t;
1533
1534 /// information about each possible shader permutation
1535 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1536 /// currently selected permutation
1537 r_hlsl_permutation_t *r_hlsl_permutation;
1538 /// storage for permutations linked in the hash table
1539 memexpandablearray_t r_hlsl_permutationarray;
1540
1541 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1542 {
1543         //unsigned int hashdepth = 0;
1544         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1545         r_hlsl_permutation_t *p;
1546         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1547         {
1548                 if (p->mode == mode && p->permutation == permutation)
1549                 {
1550                         //if (hashdepth > 10)
1551                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1552                         return p;
1553                 }
1554                 //hashdepth++;
1555         }
1556         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1557         p->mode = mode;
1558         p->permutation = permutation;
1559         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1560         r_hlsl_permutationhash[mode][hashindex] = p;
1561         //if (hashdepth > 10)
1562         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1563         return p;
1564 }
1565
1566 #include <d3dx9.h>
1567 //#include <d3dx9shader.h>
1568 //#include <d3dx9mesh.h>
1569
1570 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1571 {
1572         DWORD *vsbin = NULL;
1573         DWORD *psbin = NULL;
1574         fs_offset_t vsbinsize;
1575         fs_offset_t psbinsize;
1576 //      IDirect3DVertexShader9 *vs = NULL;
1577 //      IDirect3DPixelShader9 *ps = NULL;
1578         ID3DXBuffer *vslog = NULL;
1579         ID3DXBuffer *vsbuffer = NULL;
1580         ID3DXConstantTable *vsconstanttable = NULL;
1581         ID3DXBuffer *pslog = NULL;
1582         ID3DXBuffer *psbuffer = NULL;
1583         ID3DXConstantTable *psconstanttable = NULL;
1584         int vsresult = 0;
1585         int psresult = 0;
1586         char temp[MAX_INPUTLINE];
1587         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1588         char vabuf[1024];
1589         qboolean debugshader = gl_paranoid.integer != 0;
1590         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1592         if (!debugshader)
1593         {
1594                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1595                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1596         }
1597         if ((!vsbin && vertstring) || (!psbin && fragstring))
1598         {
1599                 const char* dllnames_d3dx9 [] =
1600                 {
1601                         "d3dx9_43.dll",
1602                         "d3dx9_42.dll",
1603                         "d3dx9_41.dll",
1604                         "d3dx9_40.dll",
1605                         "d3dx9_39.dll",
1606                         "d3dx9_38.dll",
1607                         "d3dx9_37.dll",
1608                         "d3dx9_36.dll",
1609                         "d3dx9_35.dll",
1610                         "d3dx9_34.dll",
1611                         "d3dx9_33.dll",
1612                         "d3dx9_32.dll",
1613                         "d3dx9_31.dll",
1614                         "d3dx9_30.dll",
1615                         "d3dx9_29.dll",
1616                         "d3dx9_28.dll",
1617                         "d3dx9_27.dll",
1618                         "d3dx9_26.dll",
1619                         "d3dx9_25.dll",
1620                         "d3dx9_24.dll",
1621                         NULL
1622                 };
1623                 dllhandle_t d3dx9_dll = NULL;
1624                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1626                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1627                 dllfunction_t d3dx9_dllfuncs[] =
1628                 {
1629                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1630                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1631                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1632                         {NULL, NULL}
1633                 };
1634                 // 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...
1635 #ifndef ID3DXBuffer_GetBufferPointer
1636 #if !defined(__cplusplus) || defined(CINTERFACE)
1637 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1638 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1639 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1640 #else
1641 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1642 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1643 #define ID3DXBuffer_Release(p)            (p)->Release()
1644 #endif
1645 #endif
1646                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1647                 {
1648                         DWORD shaderflags = 0;
1649                         if (debugshader)
1650                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1651                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1652                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1653                         if (vertstring && vertstring[0])
1654                         {
1655                                 if (debugshader)
1656                                 {
1657                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1658                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1659                                 }
1660                                 else
1661                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1662                                 if (vsbuffer)
1663                                 {
1664                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1665                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1666                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1667                                         ID3DXBuffer_Release(vsbuffer);
1668                                 }
1669                                 if (vslog)
1670                                 {
1671                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1672                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1673                                         ID3DXBuffer_Release(vslog);
1674                                 }
1675                         }
1676                         if (fragstring && fragstring[0])
1677                         {
1678                                 if (debugshader)
1679                                 {
1680                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1681                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1682                                 }
1683                                 else
1684                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1685                                 if (psbuffer)
1686                                 {
1687                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1688                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1689                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1690                                         ID3DXBuffer_Release(psbuffer);
1691                                 }
1692                                 if (pslog)
1693                                 {
1694                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1695                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1696                                         ID3DXBuffer_Release(pslog);
1697                                 }
1698                         }
1699                         Sys_UnloadLibrary(&d3dx9_dll);
1700                 }
1701                 else
1702                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1703         }
1704         if (vsbin && psbin)
1705         {
1706                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1707                 if (FAILED(vsresult))
1708                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1709                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1710                 if (FAILED(psresult))
1711                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1712         }
1713         // free the shader data
1714         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1715         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1716 }
1717
1718 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1719 {
1720         int i;
1721         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1722         int vertstring_length = 0;
1723         int geomstring_length = 0;
1724         int fragstring_length = 0;
1725         char *t;
1726         char *sourcestring;
1727         char *vertstring, *geomstring, *fragstring;
1728         char permutationname[256];
1729         char cachename[256];
1730         int vertstrings_count = 0;
1731         int geomstrings_count = 0;
1732         int fragstrings_count = 0;
1733         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1736
1737         if (p->compiled)
1738                 return;
1739         p->compiled = true;
1740         p->vertexshader = NULL;
1741         p->pixelshader = NULL;
1742
1743         permutationname[0] = 0;
1744         cachename[0] = 0;
1745         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1746
1747         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1748         strlcat(cachename, "hlsl/", sizeof(cachename));
1749
1750         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1751         vertstrings_count = 0;
1752         geomstrings_count = 0;
1753         fragstrings_count = 0;
1754         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1755         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1756         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1757
1758         // the first pretext is which type of shader to compile as
1759         // (later these will all be bound together as a program object)
1760         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1761         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1762         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1763
1764         // the second pretext is the mode (for example a light source)
1765         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1766         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1767         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1768         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1769         strlcat(cachename, modeinfo->name, sizeof(cachename));
1770
1771         // now add all the permutation pretexts
1772         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1773         {
1774                 if (permutation & (1<<i))
1775                 {
1776                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1777                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1778                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1779                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1780                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1781                 }
1782                 else
1783                 {
1784                         // keep line numbers correct
1785                         vertstrings_list[vertstrings_count++] = "\n";
1786                         geomstrings_list[geomstrings_count++] = "\n";
1787                         fragstrings_list[fragstrings_count++] = "\n";
1788                 }
1789         }
1790
1791         // add static parms
1792         R_CompileShader_AddStaticParms(mode, permutation);
1793         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794         vertstrings_count += shaderstaticparms_count;
1795         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796         geomstrings_count += shaderstaticparms_count;
1797         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798         fragstrings_count += shaderstaticparms_count;
1799
1800         // replace spaces in the cachename with _ characters
1801         for (i = 0;cachename[i];i++)
1802                 if (cachename[i] == ' ')
1803                         cachename[i] = '_';
1804
1805         // now append the shader text itself
1806         vertstrings_list[vertstrings_count++] = sourcestring;
1807         geomstrings_list[geomstrings_count++] = sourcestring;
1808         fragstrings_list[fragstrings_count++] = sourcestring;
1809
1810         vertstring_length = 0;
1811         for (i = 0;i < vertstrings_count;i++)
1812                 vertstring_length += (int)strlen(vertstrings_list[i]);
1813         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1814         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1815                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1816
1817         geomstring_length = 0;
1818         for (i = 0;i < geomstrings_count;i++)
1819                 geomstring_length += (int)strlen(geomstrings_list[i]);
1820         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1821         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1822                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1823
1824         fragstring_length = 0;
1825         for (i = 0;i < fragstrings_count;i++)
1826                 fragstring_length += (int)strlen(fragstrings_list[i]);
1827         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1828         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1829                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1830
1831         // try to load the cached shader, or generate one
1832         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1833
1834         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1835                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1836         else
1837                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1838
1839         // free the strings
1840         if (vertstring)
1841                 Mem_Free(vertstring);
1842         if (geomstring)
1843                 Mem_Free(geomstring);
1844         if (fragstring)
1845                 Mem_Free(fragstring);
1846         if (sourcestring)
1847                 Mem_Free(sourcestring);
1848 }
1849
1850 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1851 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1852 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);}
1853 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);}
1854 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);}
1855 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);}
1856
1857 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1858 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1859 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);}
1860 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);}
1861 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);}
1862 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);}
1863
1864 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1865 {
1866         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1867         if (r_hlsl_permutation != perm)
1868         {
1869                 r_hlsl_permutation = perm;
1870                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1871                 {
1872                         if (!r_hlsl_permutation->compiled)
1873                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1874                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1875                         {
1876                                 // remove features until we find a valid permutation
1877                                 int i;
1878                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879                                 {
1880                                         // reduce i more quickly whenever it would not remove any bits
1881                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1882                                         if (!(permutation & j))
1883                                                 continue;
1884                                         permutation -= j;
1885                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1886                                         if (!r_hlsl_permutation->compiled)
1887                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1888                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1889                                                 break;
1890                                 }
1891                                 if (i >= SHADERPERMUTATION_COUNT)
1892                                 {
1893                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1894                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1895                                         return; // no bit left to clear, entire mode is broken
1896                                 }
1897                         }
1898                 }
1899                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1900                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1901         }
1902         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1903         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1904         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1905 }
1906 #endif
1907
1908 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1909 {
1910         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1911         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1912         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1913         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1914 }
1915
1916 void R_GLSL_Restart_f(void)
1917 {
1918         unsigned int i, limit;
1919         switch(vid.renderpath)
1920         {
1921         case RENDERPATH_D3D9:
1922 #ifdef SUPPORTD3D
1923                 {
1924                         r_hlsl_permutation_t *p;
1925                         r_hlsl_permutation = NULL;
1926                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1927                         for (i = 0;i < limit;i++)
1928                         {
1929                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1930                                 {
1931                                         if (p->vertexshader)
1932                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1933                                         if (p->pixelshader)
1934                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1935                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1936                                 }
1937                         }
1938                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1939                 }
1940 #endif
1941                 break;
1942         case RENDERPATH_D3D10:
1943                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_D3D11:
1946                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947                 break;
1948         case RENDERPATH_GL20:
1949         case RENDERPATH_GLES2:
1950                 {
1951                         r_glsl_permutation_t *p;
1952                         r_glsl_permutation = NULL;
1953                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1954                         for (i = 0;i < limit;i++)
1955                         {
1956                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1957                                 {
1958                                         GL_Backend_FreeProgram(p->program);
1959                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1960                                 }
1961                         }
1962                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1963                 }
1964                 break;
1965         case RENDERPATH_GL11:
1966         case RENDERPATH_GL13:
1967         case RENDERPATH_GLES1:
1968                 break;
1969         case RENDERPATH_SOFT:
1970                 break;
1971         }
1972 }
1973
1974 static void R_GLSL_DumpShader_f(void)
1975 {
1976         int i, language, mode, dupe;
1977         char *text;
1978         shadermodeinfo_t *modeinfo;
1979         qfile_t *file;
1980
1981         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1982         {
1983                 modeinfo = shadermodeinfo[language];
1984                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1985                 {
1986                         // don't dump the same file multiple times (most or all shaders come from the same file)
1987                         for (dupe = mode - 1;dupe >= 0;dupe--)
1988                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1989                                         break;
1990                         if (dupe >= 0)
1991                                 continue;
1992                         text = modeinfo[mode].builtinstring;
1993                         if (!text)
1994                                 continue;
1995                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1996                         if (file)
1997                         {
1998                                 FS_Print(file, "/* The engine may define the following macros:\n");
1999                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2000                                 for (i = 0;i < SHADERMODE_COUNT;i++)
2001                                         FS_Print(file, modeinfo[i].pretext);
2002                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2003                                         FS_Print(file, shaderpermutationinfo[i].pretext);
2004                                 FS_Print(file, "*/\n");
2005                                 FS_Print(file, text);
2006                                 FS_Close(file);
2007                                 Con_Printf("%s written\n", modeinfo[mode].filename);
2008                         }
2009                         else
2010                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2011                 }
2012         }
2013 }
2014
2015 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2016 {
2017         unsigned int permutation = 0;
2018         if (r_trippy.integer && !notrippy)
2019                 permutation |= SHADERPERMUTATION_TRIPPY;
2020         permutation |= SHADERPERMUTATION_VIEWTINT;
2021         if (first)
2022                 permutation |= SHADERPERMUTATION_DIFFUSE;
2023         if (second)
2024                 permutation |= SHADERPERMUTATION_SPECULAR;
2025         if (texturemode == GL_MODULATE)
2026                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2027         else if (texturemode == GL_ADD)
2028                 permutation |= SHADERPERMUTATION_GLOW;
2029         else if (texturemode == GL_DECAL)
2030                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2031         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2032                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2033         if (suppresstexalpha)
2034                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2035         if (!second)
2036                 texturemode = GL_MODULATE;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTD3D
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2044                 R_Mesh_TexBind(GL20TU_FIRST , first );
2045                 R_Mesh_TexBind(GL20TU_SECOND, second);
2046                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2047                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2048 #endif
2049                 break;
2050         case RENDERPATH_D3D10:
2051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052                 break;
2053         case RENDERPATH_D3D11:
2054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2055                 break;
2056         case RENDERPATH_GL20:
2057         case RENDERPATH_GLES2:
2058                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2059                 if (r_glsl_permutation->tex_Texture_First >= 0)
2060                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2061                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2062                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2063                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2064                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2065                 break;
2066         case RENDERPATH_GL13:
2067         case RENDERPATH_GLES1:
2068                 R_Mesh_TexBind(0, first );
2069                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2070                 R_Mesh_TexMatrix(0, NULL);
2071                 R_Mesh_TexBind(1, second);
2072                 if (second)
2073                 {
2074                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2075                         R_Mesh_TexMatrix(1, NULL);
2076                 }
2077                 break;
2078         case RENDERPATH_GL11:
2079                 R_Mesh_TexBind(0, first );
2080                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2081                 R_Mesh_TexMatrix(0, NULL);
2082                 break;
2083         case RENDERPATH_SOFT:
2084                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2085                 R_Mesh_TexBind(GL20TU_FIRST , first );
2086                 R_Mesh_TexBind(GL20TU_SECOND, second);
2087                 break;
2088         }
2089 }
2090
2091 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2092 {
2093         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2094 }
2095
2096 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2097 {
2098         unsigned int permutation = 0;
2099         if (r_trippy.integer && !notrippy)
2100                 permutation |= SHADERPERMUTATION_TRIPPY;
2101         if (depthrgb)
2102                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2103         if (skeletal)
2104                 permutation |= SHADERPERMUTATION_SKELETAL;
2105
2106         if (vid.allowalphatocoverage)
2107                 GL_AlphaToCoverage(false);
2108         switch (vid.renderpath)
2109         {
2110         case RENDERPATH_D3D9:
2111 #ifdef SUPPORTD3D
2112                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2113 #endif
2114                 break;
2115         case RENDERPATH_D3D10:
2116                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2117                 break;
2118         case RENDERPATH_D3D11:
2119                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2120                 break;
2121         case RENDERPATH_GL20:
2122         case RENDERPATH_GLES2:
2123                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2124 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2125                 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);
2126 #endif
2127                 break;
2128         case RENDERPATH_GL13:
2129         case RENDERPATH_GLES1:
2130                 R_Mesh_TexBind(0, 0);
2131                 R_Mesh_TexBind(1, 0);
2132                 break;
2133         case RENDERPATH_GL11:
2134                 R_Mesh_TexBind(0, 0);
2135                 break;
2136         case RENDERPATH_SOFT:
2137                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2138                 break;
2139         }
2140 }
2141
2142 extern qboolean r_shadow_usingdeferredprepass;
2143 extern rtexture_t *r_shadow_attenuationgradienttexture;
2144 extern rtexture_t *r_shadow_attenuation2dtexture;
2145 extern rtexture_t *r_shadow_attenuation3dtexture;
2146 extern qboolean r_shadow_usingshadowmap2d;
2147 extern qboolean r_shadow_usingshadowmaportho;
2148 extern float r_shadow_modelshadowmap_texturescale[4];
2149 extern float r_shadow_modelshadowmap_parameters[4];
2150 extern float r_shadow_lightshadowmap_texturescale[4];
2151 extern float r_shadow_lightshadowmap_parameters[4];
2152 extern qboolean r_shadow_shadowmapvsdct;
2153 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2154 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2155 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2156 extern matrix4x4_t r_shadow_shadowmapmatrix;
2157 extern int r_shadow_prepass_width;
2158 extern int r_shadow_prepass_height;
2159 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2160 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2161 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2162 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2163
2164 #define BLENDFUNC_ALLOWS_COLORMOD      1
2165 #define BLENDFUNC_ALLOWS_FOG           2
2166 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2167 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2168 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2169 static int R_BlendFuncFlags(int src, int dst)
2170 {
2171         int r = 0;
2172
2173         // a blendfunc allows colormod if:
2174         // a) it can never keep the destination pixel invariant, or
2175         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2176         // this is to prevent unintended side effects from colormod
2177
2178         // a blendfunc allows fog if:
2179         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2180         // this is to prevent unintended side effects from fog
2181
2182         // these checks are the output of fogeval.pl
2183
2184         r |= BLENDFUNC_ALLOWS_COLORMOD;
2185         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2189         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2194         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2196         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2198         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2201         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2202         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2205         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206
2207         return r;
2208 }
2209
2210 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2211 {
2212         // select a permutation of the lighting shader appropriate to this
2213         // combination of texture, entity, light source, and fogging, only use the
2214         // minimum features necessary to avoid wasting rendering time in the
2215         // fragment shader on features that are not being used
2216         unsigned int permutation = 0;
2217         unsigned int mode = 0;
2218         int blendfuncflags;
2219         static float dummy_colormod[3] = {1, 1, 1};
2220         float *colormod = rsurface.colormod;
2221         float m16f[16];
2222         matrix4x4_t tempmatrix;
2223         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2224         if (r_trippy.integer && !notrippy)
2225                 permutation |= SHADERPERMUTATION_TRIPPY;
2226         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2227                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2228         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2229                 permutation |= SHADERPERMUTATION_OCCLUDE;
2230         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2231                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2232         if (rsurfacepass == RSURFPASS_BACKGROUND)
2233         {
2234                 // distorted background
2235                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2236                 {
2237                         mode = SHADERMODE_WATER;
2238                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2239                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2240                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2241                         {
2242                                 // this is the right thing to do for wateralpha
2243                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2244                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2245                         }
2246                         else
2247                         {
2248                                 // this is the right thing to do for entity alpha
2249                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2251                         }
2252                 }
2253                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2254                 {
2255                         mode = SHADERMODE_REFRACTION;
2256                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2257                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2258                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2260                 }
2261                 else
2262                 {
2263                         mode = SHADERMODE_GENERIC;
2264                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2265                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2267                 }
2268                 if (vid.allowalphatocoverage)
2269                         GL_AlphaToCoverage(false);
2270         }
2271         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2272         {
2273                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2274                 {
2275                         switch(rsurface.texture->offsetmapping)
2276                         {
2277                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2278                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2280                         case OFFSETMAPPING_OFF: break;
2281                         }
2282                 }
2283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285                 // normalmap (deferred prepass), may use alpha test on diffuse
2286                 mode = SHADERMODE_DEFERREDGEOMETRY;
2287                 GL_BlendFunc(GL_ONE, GL_ZERO);
2288                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2289                 if (vid.allowalphatocoverage)
2290                         GL_AlphaToCoverage(false);
2291         }
2292         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2293         {
2294                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2295                 {
2296                         switch(rsurface.texture->offsetmapping)
2297                         {
2298                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_OFF: break;
2302                         }
2303                 }
2304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2307                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2308                 // light source
2309                 mode = SHADERMODE_LIGHTSOURCE;
2310                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2311                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2312                 if (diffusescale > 0)
2313                         permutation |= SHADERPERMUTATION_DIFFUSE;
2314                 if (specularscale > 0)
2315                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2316                 if (r_refdef.fogenabled)
2317                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2318                 if (rsurface.texture->colormapping)
2319                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2320                 if (r_shadow_usingshadowmap2d)
2321                 {
2322                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323                         if(r_shadow_shadowmapvsdct)
2324                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2325
2326                         if (r_shadow_shadowmap2ddepthbuffer)
2327                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2328                 }
2329                 if (rsurface.texture->reflectmasktexture)
2330                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2331                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2332                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2333                 if (vid.allowalphatocoverage)
2334                         GL_AlphaToCoverage(false);
2335         }
2336         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2337         {
2338                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2339                 {
2340                         switch(rsurface.texture->offsetmapping)
2341                         {
2342                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345                         case OFFSETMAPPING_OFF: break;
2346                         }
2347                 }
2348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2351                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2352                 // unshaded geometry (fullbright or ambient model lighting)
2353                 mode = SHADERMODE_FLATCOLOR;
2354                 ambientscale = diffusescale = specularscale = 0;
2355                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2356                         permutation |= SHADERPERMUTATION_GLOW;
2357                 if (r_refdef.fogenabled)
2358                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2359                 if (rsurface.texture->colormapping)
2360                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2361                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2362                 {
2363                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2364                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2365
2366                         if (r_shadow_shadowmap2ddepthbuffer)
2367                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2368                 }
2369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370                         permutation |= SHADERPERMUTATION_REFLECTION;
2371                 if (rsurface.texture->reflectmasktexture)
2372                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2373                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2375                 // when using alphatocoverage, we don't need alphakill
2376                 if (vid.allowalphatocoverage)
2377                 {
2378                         if (r_transparent_alphatocoverage.integer)
2379                         {
2380                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2381                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2382                         }
2383                         else
2384                                 GL_AlphaToCoverage(false);
2385                 }
2386         }
2387         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2388         {
2389                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2390                 {
2391                         switch(rsurface.texture->offsetmapping)
2392                         {
2393                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2394                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2396                         case OFFSETMAPPING_OFF: break;
2397                         }
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2402                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2403                 // directional model lighting
2404                 mode = SHADERMODE_LIGHTDIRECTION;
2405                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2406                         permutation |= SHADERPERMUTATION_GLOW;
2407                 permutation |= SHADERPERMUTATION_DIFFUSE;
2408                 if (specularscale > 0)
2409                         permutation |= SHADERPERMUTATION_SPECULAR;
2410                 if (r_refdef.fogenabled)
2411                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2412                 if (rsurface.texture->colormapping)
2413                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2414                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2415                 {
2416                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2417                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2418
2419                         if (r_shadow_shadowmap2ddepthbuffer)
2420                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2421                 }
2422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2423                         permutation |= SHADERPERMUTATION_REFLECTION;
2424                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2425                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2426                 if (rsurface.texture->reflectmasktexture)
2427                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2428                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2429                 {
2430                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2431                         if (r_shadow_bouncegrid_state.directional)
2432                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2433                 }
2434                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436                 // when using alphatocoverage, we don't need alphakill
2437                 if (vid.allowalphatocoverage)
2438                 {
2439                         if (r_transparent_alphatocoverage.integer)
2440                         {
2441                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2442                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2443                         }
2444                         else
2445                                 GL_AlphaToCoverage(false);
2446                 }
2447         }
2448         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2449         {
2450                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2451                 {
2452                         switch(rsurface.texture->offsetmapping)
2453                         {
2454                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2455                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2457                         case OFFSETMAPPING_OFF: break;
2458                         }
2459                 }
2460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2463                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2464                 // ambient model lighting
2465                 mode = SHADERMODE_LIGHTDIRECTION;
2466                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2467                         permutation |= SHADERPERMUTATION_GLOW;
2468                 if (r_refdef.fogenabled)
2469                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2470                 if (rsurface.texture->colormapping)
2471                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2472                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2473                 {
2474                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2475                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2476
2477                         if (r_shadow_shadowmap2ddepthbuffer)
2478                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2479                 }
2480                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2481                         permutation |= SHADERPERMUTATION_REFLECTION;
2482                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2483                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2484                 if (rsurface.texture->reflectmasktexture)
2485                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2486                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2487                 {
2488                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489                         if (r_shadow_bouncegrid_state.directional)
2490                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2491                 }
2492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 // when using alphatocoverage, we don't need alphakill
2495                 if (vid.allowalphatocoverage)
2496                 {
2497                         if (r_transparent_alphatocoverage.integer)
2498                         {
2499                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2501                         }
2502                         else
2503                                 GL_AlphaToCoverage(false);
2504                 }
2505         }
2506         else
2507         {
2508                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2509                 {
2510                         switch(rsurface.texture->offsetmapping)
2511                         {
2512                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2513                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2514                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2515                         case OFFSETMAPPING_OFF: break;
2516                         }
2517                 }
2518                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2519                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2520                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2521                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2522                 // lightmapped wall
2523                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2524                         permutation |= SHADERPERMUTATION_GLOW;
2525                 if (r_refdef.fogenabled)
2526                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2527                 if (rsurface.texture->colormapping)
2528                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2529                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2530                 {
2531                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2532                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2533
2534                         if (r_shadow_shadowmap2ddepthbuffer)
2535                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2536                 }
2537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2538                         permutation |= SHADERPERMUTATION_REFLECTION;
2539                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2540                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2541                 if (rsurface.texture->reflectmasktexture)
2542                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2543                 if (FAKELIGHT_ENABLED)
2544                 {
2545                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2546                         mode = SHADERMODE_FAKELIGHT;
2547                         permutation |= SHADERPERMUTATION_DIFFUSE;
2548                         if (specularscale > 0)
2549                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2550                 }
2551                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2552                 {
2553                         // deluxemapping (light direction texture)
2554                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2555                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2556                         else
2557                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2558                         permutation |= SHADERPERMUTATION_DIFFUSE;
2559                         if (specularscale > 0)
2560                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2561                 }
2562                 else if (r_glsl_deluxemapping.integer >= 2)
2563                 {
2564                         // fake deluxemapping (uniform light direction in tangentspace)
2565                         if (rsurface.uselightmaptexture)
2566                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2567                         else
2568                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2569                         permutation |= SHADERPERMUTATION_DIFFUSE;
2570                         if (specularscale > 0)
2571                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2572                 }
2573                 else if (rsurface.uselightmaptexture)
2574                 {
2575                         // ordinary lightmapping (q1bsp, q3bsp)
2576                         mode = SHADERMODE_LIGHTMAP;
2577                 }
2578                 else
2579                 {
2580                         // ordinary vertex coloring (q3bsp)
2581                         mode = SHADERMODE_VERTEXCOLOR;
2582                 }
2583                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2584                 {
2585                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2586                         if (r_shadow_bouncegrid_state.directional)
2587                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2588                 }
2589                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2590                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2591                 // when using alphatocoverage, we don't need alphakill
2592                 if (vid.allowalphatocoverage)
2593                 {
2594                         if (r_transparent_alphatocoverage.integer)
2595                         {
2596                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2597                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2598                         }
2599                         else
2600                                 GL_AlphaToCoverage(false);
2601                 }
2602         }
2603         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2604                 colormod = dummy_colormod;
2605         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2606                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2607         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2608                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2609         switch(vid.renderpath)
2610         {
2611         case RENDERPATH_D3D9:
2612 #ifdef SUPPORTD3D
2613                 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);
2614                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2615                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2616                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2617                 if (mode == SHADERMODE_LIGHTSOURCE)
2618                 {
2619                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2620                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2621                 }
2622                 else
2623                 {
2624                         if (mode == SHADERMODE_LIGHTDIRECTION)
2625                         {
2626                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2627                         }
2628                 }
2629                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2630                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2631                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2632                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2634
2635                 if (mode == SHADERMODE_LIGHTSOURCE)
2636                 {
2637                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2638                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2639                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2640                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2641                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2642
2643                         // additive passes are only darkened by fog, not tinted
2644                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2645                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2646                 }
2647                 else
2648                 {
2649                         if (mode == SHADERMODE_FLATCOLOR)
2650                         {
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2652                         }
2653                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2654                         {
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2661                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2662                         }
2663                         else
2664                         {
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2666                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2667                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2668                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2669                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2670                         }
2671                         // additive passes are only darkened by fog, not tinted
2672                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2673                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2674                         else
2675                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2676                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2677                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2678                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2679                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2680                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2681                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2682                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2683                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2684                         if (mode == SHADERMODE_WATER)
2685                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2686                 }
2687                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2688                 {
2689                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2690                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2691                 }
2692                 else
2693                 {
2694                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2695                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2696                 }
2697                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2698                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2699                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2700                 if (rsurface.texture->pantstexture)
2701                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2702                 else
2703                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2704                 if (rsurface.texture->shirttexture)
2705                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2706                 else
2707                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2708                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2709                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2710                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2711                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2712                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2713                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2714                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2716                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2717                         );
2718                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2719                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2720                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2721                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2722
2723                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2724                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2725                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2726                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2727                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2728                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2729                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2730                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2731                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2732                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2733                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2734                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2735                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2736                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2737                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2738                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2739                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2740                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2741                 {
2742                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2743                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2744                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2745                 }
2746                 else
2747                 {
2748                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2749                 }
2750 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2751                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2752                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2753                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2754                 {
2755                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2756                         if (rsurface.rtlight)
2757                         {
2758                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2759                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2760                         }
2761                 }
2762 #endif
2763                 break;
2764         case RENDERPATH_D3D10:
2765                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2766                 break;
2767         case RENDERPATH_D3D11:
2768                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2769                 break;
2770         case RENDERPATH_GL20:
2771         case RENDERPATH_GLES2:
2772                 if (!vid.useinterleavedarrays)
2773                 {
2774                         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);
2775                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2776                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2777                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2778                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2779                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2780                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2781                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2782                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2783                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2784                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2785                 }
2786                 else
2787                 {
2788                         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);
2789                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2790                 }
2791                 // this has to be after RSurf_PrepareVerticesForBatch
2792                 if (rsurface.batchskeletaltransform3x4buffer)
2793                         permutation |= SHADERPERMUTATION_SKELETAL;
2794                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2795 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2796                 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);
2797 #endif
2798                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2799                 if (mode == SHADERMODE_LIGHTSOURCE)
2800                 {
2801                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2802                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2803                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2804                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2805                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2806                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2807         
2808                         // additive passes are only darkened by fog, not tinted
2809                         if (r_glsl_permutation->loc_FogColor >= 0)
2810                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2811                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2812                 }
2813                 else
2814                 {
2815                         if (mode == SHADERMODE_FLATCOLOR)
2816                         {
2817                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2818                         }
2819                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2820                         {
2821                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2822                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2823                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2824                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2825                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2826                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2827                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2828                         }
2829                         else
2830                         {
2831                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2832                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2833                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2834                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2836                         }
2837                         // additive passes are only darkened by fog, not tinted
2838                         if (r_glsl_permutation->loc_FogColor >= 0)
2839                         {
2840                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2841                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2842                                 else
2843                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2844                         }
2845                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2846                         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]);
2847                         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]);
2848                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2849                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2850                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2851                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2852                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2853                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2854                 }
2855                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2856                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2857                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2858                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2859                 {
2860                         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]);
2861                         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]);
2862                 }
2863                 else
2864                 {
2865                         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]);
2866                         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]);
2867                 }
2868
2869                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2870                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2871                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2872                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2873                 {
2874                         if (rsurface.texture->pantstexture)
2875                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2876                         else
2877                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2878                 }
2879                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2880                 {
2881                         if (rsurface.texture->shirttexture)
2882                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2883                         else
2884                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2885                 }
2886                 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]);
2887                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2888                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2889                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2890                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2891                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2892                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2893                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2894                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2895                         );
2896                 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);
2897                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2898                 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]);
2899                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2900                 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);}
2901                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2902
2903                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2904                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2905                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2906                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2907                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2908                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2909                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2910                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2911                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2912                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2913                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2914                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2915                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2916                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2917                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2918                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2919                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2920                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2921                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2922                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2923                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2924                 {
2925                         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);
2926                         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);
2927                         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);
2928                 }
2929                 else
2930                 {
2931                         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);
2932                 }
2933                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2934                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2935                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2936                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2937                 {
2938                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2939                         if (rsurface.rtlight)
2940                         {
2941                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2942                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2943                         }
2944                 }
2945                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2946                 CHECKGLERROR
2947                 break;
2948         case RENDERPATH_GL11:
2949         case RENDERPATH_GL13:
2950         case RENDERPATH_GLES1:
2951                 break;
2952         case RENDERPATH_SOFT:
2953                 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);
2954                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2955                 R_SetupShader_SetPermutationSoft(mode, permutation);
2956                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2957                 if (mode == SHADERMODE_LIGHTSOURCE)
2958                 {
2959                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2960                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2961                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2962                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2963                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2964                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2965         
2966                         // additive passes are only darkened by fog, not tinted
2967                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2968                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2969                 }
2970                 else
2971                 {
2972                         if (mode == SHADERMODE_FLATCOLOR)
2973                         {
2974                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2975                         }
2976                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2977                         {
2978                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2979                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2981                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2982                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2984                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2985                         }
2986                         else
2987                         {
2988                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2989                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2990                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2991                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2992                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2993                         }
2994                         // additive passes are only darkened by fog, not tinted
2995                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2996                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2997                         else
2998                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2999                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
3000                         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]);
3001                         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]);
3002                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3003                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3004                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3005                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3006                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3007                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3008                 }
3009                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3010                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3011                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3012                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3013                 {
3014                         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]);
3015                         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]);
3016                 }
3017                 else
3018                 {
3019                         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]);
3020                         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]);
3021                 }
3022
3023                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3024                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3025                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3026                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3027                 {
3028                         if (rsurface.texture->pantstexture)
3029                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3030                         else
3031                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3032                 }
3033                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3034                 {
3035                         if (rsurface.texture->shirttexture)
3036                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3037                         else
3038                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3039                 }
3040                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3041                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3042                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3043                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3044                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3045                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3046                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3047                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3048                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3049                         );
3050                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3051                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3052                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3054
3055                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3056                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3057                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3058                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3059                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3060                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3061                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3062                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3063                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3064                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3065                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3066                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3067                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3068                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3069                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3070                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3071                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3072                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3073                 {
3074                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3075                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3076                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3077                 }
3078                 else
3079                 {
3080                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3081                 }
3082 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3083                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3084                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3085                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3086                 {
3087                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3088                         if (rsurface.rtlight)
3089                         {
3090                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3091                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3092                         }
3093                 }
3094                 break;
3095         }
3096 }
3097
3098 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3099 {
3100         // select a permutation of the lighting shader appropriate to this
3101         // combination of texture, entity, light source, and fogging, only use the
3102         // minimum features necessary to avoid wasting rendering time in the
3103         // fragment shader on features that are not being used
3104         unsigned int permutation = 0;
3105         unsigned int mode = 0;
3106         const float *lightcolorbase = rtlight->currentcolor;
3107         float ambientscale = rtlight->ambientscale;
3108         float diffusescale = rtlight->diffusescale;
3109         float specularscale = rtlight->specularscale;
3110         // this is the location of the light in view space
3111         vec3_t viewlightorigin;
3112         // this transforms from view space (camera) to light space (cubemap)
3113         matrix4x4_t viewtolight;
3114         matrix4x4_t lighttoview;
3115         float viewtolight16f[16];
3116         // light source
3117         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3118         if (rtlight->currentcubemap != r_texture_whitecube)
3119                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3120         if (diffusescale > 0)
3121                 permutation |= SHADERPERMUTATION_DIFFUSE;
3122         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3123                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3124         if (r_shadow_usingshadowmap2d)
3125         {
3126                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3127                 if (r_shadow_shadowmapvsdct)
3128                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3129
3130                 if (r_shadow_shadowmap2ddepthbuffer)
3131                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3132         }
3133         if (vid.allowalphatocoverage)
3134                 GL_AlphaToCoverage(false);
3135         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3136         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3137         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3138         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3139         switch(vid.renderpath)
3140         {
3141         case RENDERPATH_D3D9:
3142 #ifdef SUPPORTD3D
3143                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3144                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3145                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3146                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3147                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3148                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3149                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3150                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3151                 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);
3152                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3153                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3154
3155                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3156                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3157                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3158                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3159                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3160 #endif
3161                 break;
3162         case RENDERPATH_D3D10:
3163                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3164                 break;
3165         case RENDERPATH_D3D11:
3166                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3167                 break;
3168         case RENDERPATH_GL20:
3169         case RENDERPATH_GLES2:
3170                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3171                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3172                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3173                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3174                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3175                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3176                 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]);
3177                 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]);
3178                 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);
3179                 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]);
3180                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3181
3182                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3183                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3184                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3185                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3186                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3187                 break;
3188         case RENDERPATH_GL11:
3189         case RENDERPATH_GL13:
3190         case RENDERPATH_GLES1:
3191                 break;
3192         case RENDERPATH_SOFT:
3193                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3194                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3195                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3196                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3197                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3198                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3199                 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]);
3200                 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]);
3201                 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);
3202                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3203                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3204
3205                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3206                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3207                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3208                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3209                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3210                 break;
3211         }
3212 }
3213
3214 #define SKINFRAME_HASH 1024
3215
3216 typedef struct
3217 {
3218         unsigned int loadsequence; // incremented each level change
3219         memexpandablearray_t array;
3220         skinframe_t *hash[SKINFRAME_HASH];
3221 }
3222 r_skinframe_t;
3223 r_skinframe_t r_skinframe;
3224
3225 void R_SkinFrame_PrepareForPurge(void)
3226 {
3227         r_skinframe.loadsequence++;
3228         // wrap it without hitting zero
3229         if (r_skinframe.loadsequence >= 200)
3230                 r_skinframe.loadsequence = 1;
3231 }
3232
3233 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3234 {
3235         if (!skinframe)
3236                 return;
3237         // mark the skinframe as used for the purging code
3238         skinframe->loadsequence = r_skinframe.loadsequence;
3239 }
3240
3241 void R_SkinFrame_Purge(void)
3242 {
3243         int i;
3244         skinframe_t *s;
3245         for (i = 0;i < SKINFRAME_HASH;i++)
3246         {
3247                 for (s = r_skinframe.hash[i];s;s = s->next)
3248                 {
3249                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3250                         {
3251                                 if (s->merged == s->base)
3252                                         s->merged = NULL;
3253                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3254                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3255                                 R_PurgeTexture(s->merged);s->merged = NULL;
3256                                 R_PurgeTexture(s->base  );s->base   = NULL;
3257                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3258                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3259                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3260                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3261                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3262                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3263                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3264                                 s->loadsequence = 0;
3265                         }
3266                 }
3267         }
3268 }
3269
3270 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3271         skinframe_t *item;
3272         char basename[MAX_QPATH];
3273
3274         Image_StripImageExtension(name, basename, sizeof(basename));
3275
3276         if( last == NULL ) {
3277                 int hashindex;
3278                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3279                 item = r_skinframe.hash[hashindex];
3280         } else {
3281                 item = last->next;
3282         }
3283
3284         // linearly search through the hash bucket
3285         for( ; item ; item = item->next ) {
3286                 if( !strcmp( item->basename, basename ) ) {
3287                         return item;
3288                 }
3289         }
3290         return NULL;
3291 }
3292
3293 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3294 {
3295         skinframe_t *item;
3296         int hashindex;
3297         char basename[MAX_QPATH];
3298
3299         Image_StripImageExtension(name, basename, sizeof(basename));
3300
3301         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3302         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3303                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3304                         break;
3305
3306         if (!item) {
3307                 rtexture_t *dyntexture;
3308                 // check whether its a dynamic texture
3309                 dyntexture = CL_GetDynTexture( basename );
3310                 if (!add && !dyntexture)
3311                         return NULL;
3312                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3313                 memset(item, 0, sizeof(*item));
3314                 strlcpy(item->basename, basename, sizeof(item->basename));
3315                 item->base = dyntexture; // either NULL or dyntexture handle
3316                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3317                 item->comparewidth = comparewidth;
3318                 item->compareheight = compareheight;
3319                 item->comparecrc = comparecrc;
3320                 item->next = r_skinframe.hash[hashindex];
3321                 r_skinframe.hash[hashindex] = item;
3322         }
3323         else if (textureflags & TEXF_FORCE_RELOAD)
3324         {
3325                 rtexture_t *dyntexture;
3326                 // check whether its a dynamic texture
3327                 dyntexture = CL_GetDynTexture( basename );
3328                 if (!add && !dyntexture)
3329                         return NULL;
3330                 if (item->merged == item->base)
3331                         item->merged = NULL;
3332                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3333                 R_PurgeTexture(item->stain );item->stain  = NULL;
3334                 R_PurgeTexture(item->merged);item->merged = NULL;
3335                 R_PurgeTexture(item->base  );item->base   = NULL;
3336                 R_PurgeTexture(item->pants );item->pants  = NULL;
3337                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3338                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3339                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3340                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3341                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3342         R_PurgeTexture(item->reflect);item->reflect = NULL;
3343                 item->loadsequence = 0;
3344         }
3345         else if( item->base == NULL )
3346         {
3347                 rtexture_t *dyntexture;
3348                 // check whether its a dynamic texture
3349                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3350                 dyntexture = CL_GetDynTexture( basename );
3351                 item->base = dyntexture; // either NULL or dyntexture handle
3352         }
3353
3354         R_SkinFrame_MarkUsed(item);
3355         return item;
3356 }
3357
3358 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3359         { \
3360                 unsigned long long avgcolor[5], wsum; \
3361                 int pix, comp, w; \
3362                 avgcolor[0] = 0; \
3363                 avgcolor[1] = 0; \
3364                 avgcolor[2] = 0; \
3365                 avgcolor[3] = 0; \
3366                 avgcolor[4] = 0; \
3367                 wsum = 0; \
3368                 for(pix = 0; pix < cnt; ++pix) \
3369                 { \
3370                         w = 0; \
3371                         for(comp = 0; comp < 3; ++comp) \
3372                                 w += getpixel; \
3373                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3374                         { \
3375                                 ++wsum; \
3376                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3377                                 w = getpixel; \
3378                                 for(comp = 0; comp < 3; ++comp) \
3379                                         avgcolor[comp] += getpixel * w; \
3380                                 avgcolor[3] += w; \
3381                         } \
3382                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3383                         avgcolor[4] += getpixel; \
3384                 } \
3385                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3386                         avgcolor[3] = 1; \
3387                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3388                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3389                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3390                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3391         }
3392
3393 extern cvar_t gl_picmip;
3394 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3395 {
3396         int j;
3397         unsigned char *pixels;
3398         unsigned char *bumppixels;
3399         unsigned char *basepixels = NULL;
3400         int basepixels_width = 0;
3401         int basepixels_height = 0;
3402         skinframe_t *skinframe;
3403         rtexture_t *ddsbase = NULL;
3404         qboolean ddshasalpha = false;
3405         float ddsavgcolor[4];
3406         char basename[MAX_QPATH];
3407         int miplevel = R_PicmipForFlags(textureflags);
3408         int savemiplevel = miplevel;
3409         int mymiplevel;
3410         char vabuf[1024];
3411
3412         if (cls.state == ca_dedicated)
3413                 return NULL;
3414
3415         // return an existing skinframe if already loaded
3416         // if loading of the first image fails, don't make a new skinframe as it
3417         // would cause all future lookups of this to be missing
3418         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3419         if (skinframe && skinframe->base)
3420                 return skinframe;
3421
3422         Image_StripImageExtension(name, basename, sizeof(basename));
3423
3424         // check for DDS texture file first
3425         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3426         {
3427                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3428                 if (basepixels == NULL)
3429                         return NULL;
3430         }
3431
3432         // FIXME handle miplevel
3433
3434         if (developer_loading.integer)
3435                 Con_Printf("loading skin \"%s\"\n", name);
3436
3437         // we've got some pixels to store, so really allocate this new texture now
3438         if (!skinframe)
3439                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3440         textureflags &= ~TEXF_FORCE_RELOAD;
3441         skinframe->stain = NULL;
3442         skinframe->merged = NULL;
3443         skinframe->base = NULL;
3444         skinframe->pants = NULL;
3445         skinframe->shirt = NULL;
3446         skinframe->nmap = NULL;
3447         skinframe->gloss = NULL;
3448         skinframe->glow = NULL;
3449         skinframe->fog = NULL;
3450         skinframe->reflect = NULL;
3451         skinframe->hasalpha = false;
3452         // we could store the q2animname here too
3453
3454         if (ddsbase)
3455         {
3456                 skinframe->base = ddsbase;
3457                 skinframe->hasalpha = ddshasalpha;
3458                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3459                 if (r_loadfog && skinframe->hasalpha)
3460                         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);
3461                 //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]);
3462         }
3463         else
3464         {
3465                 basepixels_width = image_width;
3466                 basepixels_height = image_height;
3467                 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);
3468                 if (textureflags & TEXF_ALPHA)
3469                 {
3470                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3471                         {
3472                                 if (basepixels[j] < 255)
3473                                 {
3474                                         skinframe->hasalpha = true;
3475                                         break;
3476                                 }
3477                         }
3478                         if (r_loadfog && skinframe->hasalpha)
3479                         {
3480                                 // has transparent pixels
3481                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3482                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3483                                 {
3484                                         pixels[j+0] = 255;
3485                                         pixels[j+1] = 255;
3486                                         pixels[j+2] = 255;
3487                                         pixels[j+3] = basepixels[j+3];
3488                                 }
3489                                 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);
3490                                 Mem_Free(pixels);
3491                         }
3492                 }
3493                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3494 #ifndef USE_GLES2
3495                 //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]);
3496                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3497                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3498                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3499                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3500 #endif
3501         }
3502
3503         if (r_loaddds)
3504         {
3505                 mymiplevel = savemiplevel;
3506                 if (r_loadnormalmap)
3507                         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);
3508                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3509                 if (r_loadgloss)
3510                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3511                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3512                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3513                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3514         }
3515
3516         // _norm is the name used by tenebrae and has been adopted as standard
3517         if (r_loadnormalmap && skinframe->nmap == NULL)
3518         {
3519                 mymiplevel = savemiplevel;
3520                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3521                 {
3522                         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);
3523                         Mem_Free(pixels);
3524                         pixels = NULL;
3525                 }
3526                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3527                 {
3528                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3529                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3530                         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);
3531                         Mem_Free(pixels);
3532                         Mem_Free(bumppixels);
3533                 }
3534                 else if (r_shadow_bumpscale_basetexture.value > 0)
3535                 {
3536                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3537                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3538                         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);
3539                         Mem_Free(pixels);
3540                 }
3541 #ifndef USE_GLES2
3542                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3543                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3544 #endif
3545         }
3546
3547         // _luma is supported only for tenebrae compatibility
3548         // _glow is the preferred name
3549         mymiplevel = savemiplevel;
3550         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))))
3551         {
3552                 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);
3553 #ifndef USE_GLES2
3554                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3555                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3556 #endif
3557                 Mem_Free(pixels);pixels = NULL;
3558         }
3559
3560         mymiplevel = savemiplevel;
3561         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3562         {
3563                 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);
3564 #ifndef USE_GLES2
3565                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3566                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3567 #endif
3568                 Mem_Free(pixels);
3569                 pixels = NULL;
3570         }
3571
3572         mymiplevel = savemiplevel;
3573         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3574         {
3575                 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);
3576 #ifndef USE_GLES2
3577                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3578                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3579 #endif
3580                 Mem_Free(pixels);
3581                 pixels = NULL;
3582         }
3583
3584         mymiplevel = savemiplevel;
3585         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3586         {
3587                 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);
3588 #ifndef USE_GLES2
3589                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3590                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3591 #endif
3592                 Mem_Free(pixels);
3593                 pixels = NULL;
3594         }
3595
3596         mymiplevel = savemiplevel;
3597         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3598         {
3599                 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);
3600 #ifndef USE_GLES2
3601                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3602                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3603 #endif
3604                 Mem_Free(pixels);
3605                 pixels = NULL;
3606         }
3607
3608         if (basepixels)
3609                 Mem_Free(basepixels);
3610
3611         return skinframe;
3612 }
3613
3614 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3615 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3616 {
3617         int i;
3618         skinframe_t *skinframe;
3619         char vabuf[1024];
3620
3621         if (cls.state == ca_dedicated)
3622                 return NULL;
3623
3624         // if already loaded just return it, otherwise make a new skinframe
3625         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3626         if (skinframe->base)
3627                 return skinframe;
3628         textureflags &= ~TEXF_FORCE_RELOAD;
3629
3630         skinframe->stain = NULL;
3631         skinframe->merged = NULL;
3632         skinframe->base = NULL;
3633         skinframe->pants = NULL;
3634         skinframe->shirt = NULL;
3635         skinframe->nmap = NULL;
3636         skinframe->gloss = NULL;
3637         skinframe->glow = NULL;
3638         skinframe->fog = NULL;
3639         skinframe->reflect = NULL;
3640         skinframe->hasalpha = false;
3641
3642         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3643         if (!skindata)
3644                 return NULL;
3645
3646         if (developer_loading.integer)
3647                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3648
3649         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3650         {
3651                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3652                 unsigned char *b = a + width * height * 4;
3653                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3654                 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);
3655                 Mem_Free(a);
3656         }
3657         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3658         if (textureflags & TEXF_ALPHA)
3659         {
3660                 for (i = 3;i < width * height * 4;i += 4)
3661                 {
3662                         if (skindata[i] < 255)
3663                         {
3664                                 skinframe->hasalpha = true;
3665                                 break;
3666                         }
3667                 }
3668                 if (r_loadfog && skinframe->hasalpha)
3669                 {
3670                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3671                         memcpy(fogpixels, skindata, width * height * 4);
3672                         for (i = 0;i < width * height * 4;i += 4)
3673                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3674                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3675                         Mem_Free(fogpixels);
3676                 }
3677         }
3678
3679         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3680         //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]);
3681
3682         return skinframe;
3683 }
3684
3685 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3686 {
3687         int i;
3688         int featuresmask;
3689         skinframe_t *skinframe;
3690
3691         if (cls.state == ca_dedicated)
3692                 return NULL;
3693
3694         // if already loaded just return it, otherwise make a new skinframe
3695         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3696         if (skinframe->base)
3697                 return skinframe;
3698         //textureflags &= ~TEXF_FORCE_RELOAD;
3699
3700         skinframe->stain = NULL;
3701         skinframe->merged = NULL;
3702         skinframe->base = NULL;
3703         skinframe->pants = NULL;
3704         skinframe->shirt = NULL;
3705         skinframe->nmap = NULL;
3706         skinframe->gloss = NULL;
3707         skinframe->glow = NULL;
3708         skinframe->fog = NULL;
3709         skinframe->reflect = NULL;
3710         skinframe->hasalpha = false;
3711
3712         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3713         if (!skindata)
3714                 return NULL;
3715
3716         if (developer_loading.integer)
3717                 Con_Printf("loading quake skin \"%s\"\n", name);
3718
3719         // 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)
3720         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3721         memcpy(skinframe->qpixels, skindata, width*height);
3722         skinframe->qwidth = width;
3723         skinframe->qheight = height;
3724
3725         featuresmask = 0;
3726         for (i = 0;i < width * height;i++)
3727                 featuresmask |= palette_featureflags[skindata[i]];
3728
3729         skinframe->hasalpha = false;
3730         // fence textures
3731         if (name[0] == '{')
3732                 skinframe->hasalpha = true;
3733         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3734         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3735         skinframe->qgeneratemerged = true;
3736         skinframe->qgeneratebase = skinframe->qhascolormapping;
3737         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3738
3739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3740         //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]);
3741
3742         return skinframe;
3743 }
3744
3745 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3746 {
3747         int width;
3748         int height;
3749         unsigned char *skindata;
3750         char vabuf[1024];
3751
3752         if (!skinframe->qpixels)
3753                 return;
3754
3755         if (!skinframe->qhascolormapping)
3756                 colormapped = false;
3757
3758         if (colormapped)
3759         {
3760                 if (!skinframe->qgeneratebase)
3761                         return;
3762         }
3763         else
3764         {
3765                 if (!skinframe->qgeneratemerged)
3766                         return;
3767         }
3768
3769         width = skinframe->qwidth;
3770         height = skinframe->qheight;
3771         skindata = skinframe->qpixels;
3772
3773         if (skinframe->qgeneratenmap)
3774         {
3775                 unsigned char *a, *b;
3776                 skinframe->qgeneratenmap = false;
3777                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3778                 b = a + width * height * 4;
3779                 // use either a custom palette or the quake palette
3780                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3781                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3782                 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);
3783                 Mem_Free(a);
3784         }
3785
3786         if (skinframe->qgenerateglow)
3787         {
3788                 skinframe->qgenerateglow = false;
3789                 if (skinframe->hasalpha) // fence textures
3790                         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
3791                 else
3792                         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
3793         }
3794
3795         if (colormapped)
3796         {
3797                 skinframe->qgeneratebase = false;
3798                 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);
3799                 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);
3800                 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);
3801         }
3802         else
3803         {
3804                 skinframe->qgeneratemerged = false;
3805                 if (skinframe->hasalpha) // fence textures
3806                         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);
3807                 else
3808                         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);
3809         }
3810
3811         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3812         {
3813                 Mem_Free(skinframe->qpixels);
3814                 skinframe->qpixels = NULL;
3815         }
3816 }
3817
3818 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)
3819 {
3820         int i;
3821         skinframe_t *skinframe;
3822         char vabuf[1024];
3823
3824         if (cls.state == ca_dedicated)
3825                 return NULL;
3826
3827         // if already loaded just return it, otherwise make a new skinframe
3828         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3829         if (skinframe->base)
3830                 return skinframe;
3831         textureflags &= ~TEXF_FORCE_RELOAD;
3832
3833         skinframe->stain = NULL;
3834         skinframe->merged = NULL;
3835         skinframe->base = NULL;
3836         skinframe->pants = NULL;
3837         skinframe->shirt = NULL;
3838         skinframe->nmap = NULL;
3839         skinframe->gloss = NULL;
3840         skinframe->glow = NULL;
3841         skinframe->fog = NULL;
3842         skinframe->reflect = NULL;
3843         skinframe->hasalpha = false;
3844
3845         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3846         if (!skindata)
3847                 return NULL;
3848
3849         if (developer_loading.integer)
3850                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3851
3852         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3853         if (textureflags & TEXF_ALPHA)
3854         {
3855                 for (i = 0;i < width * height;i++)
3856                 {
3857                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3858                         {
3859                                 skinframe->hasalpha = true;
3860                                 break;
3861                         }
3862                 }
3863                 if (r_loadfog && skinframe->hasalpha)
3864                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3865         }
3866
3867         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3868         //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]);
3869
3870         return skinframe;
3871 }
3872
3873 skinframe_t *R_SkinFrame_LoadMissing(void)
3874 {
3875         skinframe_t *skinframe;
3876
3877         if (cls.state == ca_dedicated)
3878                 return NULL;
3879
3880         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3881         skinframe->stain = NULL;
3882         skinframe->merged = NULL;
3883         skinframe->base = NULL;
3884         skinframe->pants = NULL;
3885         skinframe->shirt = NULL;
3886         skinframe->nmap = NULL;
3887         skinframe->gloss = NULL;
3888         skinframe->glow = NULL;
3889         skinframe->fog = NULL;
3890         skinframe->reflect = NULL;
3891         skinframe->hasalpha = false;
3892
3893         skinframe->avgcolor[0] = rand() / RAND_MAX;
3894         skinframe->avgcolor[1] = rand() / RAND_MAX;
3895         skinframe->avgcolor[2] = rand() / RAND_MAX;
3896         skinframe->avgcolor[3] = 1;
3897
3898         return skinframe;
3899 }
3900
3901 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3902 typedef struct suffixinfo_s
3903 {
3904         const char *suffix;
3905         qboolean flipx, flipy, flipdiagonal;
3906 }
3907 suffixinfo_t;
3908 static suffixinfo_t suffix[3][6] =
3909 {
3910         {
3911                 {"px",   false, false, false},
3912                 {"nx",   false, false, false},
3913                 {"py",   false, false, false},
3914                 {"ny",   false, false, false},
3915                 {"pz",   false, false, false},
3916                 {"nz",   false, false, false}
3917         },
3918         {
3919                 {"posx", false, false, false},
3920                 {"negx", false, false, false},
3921                 {"posy", false, false, false},
3922                 {"negy", false, false, false},
3923                 {"posz", false, false, false},
3924                 {"negz", false, false, false}
3925         },
3926         {
3927                 {"rt",    true, false,  true},
3928                 {"lf",   false,  true,  true},
3929                 {"ft",    true,  true, false},
3930                 {"bk",   false, false, false},
3931                 {"up",    true, false,  true},
3932                 {"dn",    true, false,  true}
3933         }
3934 };
3935
3936 static int componentorder[4] = {0, 1, 2, 3};
3937
3938 static rtexture_t *R_LoadCubemap(const char *basename)
3939 {
3940         int i, j, cubemapsize;
3941         unsigned char *cubemappixels, *image_buffer;
3942         rtexture_t *cubemaptexture;
3943         char name[256];
3944         // must start 0 so the first loadimagepixels has no requested width/height
3945         cubemapsize = 0;
3946         cubemappixels = NULL;
3947         cubemaptexture = NULL;
3948         // keep trying different suffix groups (posx, px, rt) until one loads
3949         for (j = 0;j < 3 && !cubemappixels;j++)
3950         {
3951                 // load the 6 images in the suffix group
3952                 for (i = 0;i < 6;i++)
3953                 {
3954                         // generate an image name based on the base and and suffix
3955                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3956                         // load it
3957                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3958                         {
3959                                 // an image loaded, make sure width and height are equal
3960                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3961                                 {
3962                                         // if this is the first image to load successfully, allocate the cubemap memory
3963                                         if (!cubemappixels && image_width >= 1)
3964                                         {
3965                                                 cubemapsize = image_width;
3966                                                 // note this clears to black, so unavailable sides are black
3967                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3968                                         }
3969                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3970                                         if (cubemappixels)
3971                                                 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);
3972                                 }
3973                                 else
3974                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3975                                 // free the image
3976                                 Mem_Free(image_buffer);
3977                         }
3978                 }
3979         }
3980         // if a cubemap loaded, upload it
3981         if (cubemappixels)
3982         {
3983                 if (developer_loading.integer)
3984                         Con_Printf("loading cubemap \"%s\"\n", basename);
3985
3986                 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);
3987                 Mem_Free(cubemappixels);
3988         }
3989         else
3990         {
3991                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3992                 if (developer_loading.integer)
3993                 {
3994                         Con_Printf("(tried tried images ");
3995                         for (j = 0;j < 3;j++)
3996                                 for (i = 0;i < 6;i++)
3997                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3998                         Con_Print(" and was unable to find any of them).\n");
3999                 }
4000         }
4001         return cubemaptexture;
4002 }
4003
4004 rtexture_t *R_GetCubemap(const char *basename)
4005 {
4006         int i;
4007         for (i = 0;i < r_texture_numcubemaps;i++)
4008                 if (r_texture_cubemaps[i] != NULL)
4009                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4010                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4011         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4012                 return r_texture_whitecube;
4013         r_texture_numcubemaps++;
4014         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4015         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4016         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4017         return r_texture_cubemaps[i]->texture;
4018 }
4019
4020 static void R_Main_FreeViewCache(void)
4021 {
4022         if (r_refdef.viewcache.entityvisible)
4023                 Mem_Free(r_refdef.viewcache.entityvisible);
4024         if (r_refdef.viewcache.world_pvsbits)
4025                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4026         if (r_refdef.viewcache.world_leafvisible)
4027                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4028         if (r_refdef.viewcache.world_surfacevisible)
4029                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4030         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4031 }
4032
4033 static void R_Main_ResizeViewCache(void)
4034 {
4035         int numentities = r_refdef.scene.numentities;
4036         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4037         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4038         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4039         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4040         if (r_refdef.viewcache.maxentities < numentities)
4041         {
4042                 r_refdef.viewcache.maxentities = numentities;
4043                 if (r_refdef.viewcache.entityvisible)
4044                         Mem_Free(r_refdef.viewcache.entityvisible);
4045                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4046         }
4047         if (r_refdef.viewcache.world_numclusters != numclusters)
4048         {
4049                 r_refdef.viewcache.world_numclusters = numclusters;
4050                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4051                 if (r_refdef.viewcache.world_pvsbits)
4052                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4053                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4054         }
4055         if (r_refdef.viewcache.world_numleafs != numleafs)
4056         {
4057                 r_refdef.viewcache.world_numleafs = numleafs;
4058                 if (r_refdef.viewcache.world_leafvisible)
4059                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4060                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4061         }
4062         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4063         {
4064                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4065                 if (r_refdef.viewcache.world_surfacevisible)
4066                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4067                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4068         }
4069 }
4070
4071 extern rtexture_t *loadingscreentexture;
4072 static void gl_main_start(void)
4073 {
4074         loadingscreentexture = NULL;
4075         r_texture_blanknormalmap = NULL;
4076         r_texture_white = NULL;
4077         r_texture_grey128 = NULL;
4078         r_texture_black = NULL;
4079         r_texture_whitecube = NULL;
4080         r_texture_normalizationcube = NULL;
4081         r_texture_fogattenuation = NULL;
4082         r_texture_fogheighttexture = NULL;
4083         r_texture_gammaramps = NULL;
4084         r_texture_numcubemaps = 0;
4085         r_uniformbufferalignment = 32;
4086
4087         r_loaddds = r_texture_dds_load.integer != 0;
4088         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4089
4090         switch(vid.renderpath)
4091         {
4092         case RENDERPATH_GL20:
4093         case RENDERPATH_D3D9:
4094         case RENDERPATH_D3D10:
4095         case RENDERPATH_D3D11:
4096         case RENDERPATH_SOFT:
4097         case RENDERPATH_GLES2:
4098                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4099                 Cvar_SetValueQuick(&gl_combine, 1);
4100                 Cvar_SetValueQuick(&r_glsl, 1);
4101                 r_loadnormalmap = true;
4102                 r_loadgloss = true;
4103                 r_loadfog = false;
4104 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4105                 if (vid.support.arb_uniform_buffer_object)
4106                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4107 #endif
4108                         break;
4109         case RENDERPATH_GL13:
4110         case RENDERPATH_GLES1:
4111                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4112                 Cvar_SetValueQuick(&gl_combine, 1);
4113                 Cvar_SetValueQuick(&r_glsl, 0);
4114                 r_loadnormalmap = false;
4115                 r_loadgloss = false;
4116                 r_loadfog = true;
4117                 break;
4118         case RENDERPATH_GL11:
4119                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4120                 Cvar_SetValueQuick(&gl_combine, 0);
4121                 Cvar_SetValueQuick(&r_glsl, 0);
4122                 r_loadnormalmap = false;
4123                 r_loadgloss = false;
4124                 r_loadfog = true;
4125                 break;
4126         }
4127
4128         R_AnimCache_Free();
4129         R_FrameData_Reset();
4130         R_BufferData_Reset();
4131
4132         r_numqueries = 0;
4133         r_maxqueries = 0;
4134         memset(r_queries, 0, sizeof(r_queries));
4135
4136         r_qwskincache = NULL;
4137         r_qwskincache_size = 0;
4138
4139         // due to caching of texture_t references, the collision cache must be reset
4140         Collision_Cache_Reset(true);
4141
4142         // set up r_skinframe loading system for textures
4143         memset(&r_skinframe, 0, sizeof(r_skinframe));
4144         r_skinframe.loadsequence = 1;
4145         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4146
4147         r_main_texturepool = R_AllocTexturePool();
4148         R_BuildBlankTextures();
4149         R_BuildNoTexture();
4150         if (vid.support.arb_texture_cube_map)
4151         {
4152                 R_BuildWhiteCube();
4153                 R_BuildNormalizationCube();
4154         }
4155         r_texture_fogattenuation = NULL;
4156         r_texture_fogheighttexture = NULL;
4157         r_texture_gammaramps = NULL;
4158         //r_texture_fogintensity = NULL;
4159         memset(&r_fb, 0, sizeof(r_fb));
4160         r_glsl_permutation = NULL;
4161         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4162         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4163 #ifdef SUPPORTD3D
4164         r_hlsl_permutation = NULL;
4165         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4166         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4167 #endif
4168         memset(&r_svbsp, 0, sizeof (r_svbsp));
4169
4170         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4171         r_texture_numcubemaps = 0;
4172
4173         r_refdef.fogmasktable_density = 0;
4174
4175 #ifdef __ANDROID__
4176         // For Steelstorm Android
4177         // FIXME CACHE the program and reload
4178         // FIXME see possible combinations for SS:BR android
4179         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4180         R_SetupShader_SetPermutationGLSL(0, 12);
4181         R_SetupShader_SetPermutationGLSL(0, 13);
4182         R_SetupShader_SetPermutationGLSL(0, 8388621);
4183         R_SetupShader_SetPermutationGLSL(3, 0);
4184         R_SetupShader_SetPermutationGLSL(3, 2048);
4185         R_SetupShader_SetPermutationGLSL(5, 0);
4186         R_SetupShader_SetPermutationGLSL(5, 2);
4187         R_SetupShader_SetPermutationGLSL(5, 2048);
4188         R_SetupShader_SetPermutationGLSL(5, 8388608);
4189         R_SetupShader_SetPermutationGLSL(11, 1);
4190         R_SetupShader_SetPermutationGLSL(11, 2049);
4191         R_SetupShader_SetPermutationGLSL(11, 8193);
4192         R_SetupShader_SetPermutationGLSL(11, 10241);
4193         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4194 #endif
4195 }
4196
4197 static void gl_main_shutdown(void)
4198 {
4199         R_AnimCache_Free();
4200         R_FrameData_Reset();
4201         R_BufferData_Reset();
4202
4203         R_Main_FreeViewCache();
4204
4205         switch(vid.renderpath)
4206         {
4207         case RENDERPATH_GL11:
4208         case RENDERPATH_GL13:
4209         case RENDERPATH_GL20:
4210         case RENDERPATH_GLES1:
4211         case RENDERPATH_GLES2:
4212 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4213                 if (r_maxqueries)
4214                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4215 #endif
4216                 break;
4217         case RENDERPATH_D3D9:
4218                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4219                 break;
4220         case RENDERPATH_D3D10:
4221                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4222                 break;
4223         case RENDERPATH_D3D11:
4224                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4225                 break;
4226         case RENDERPATH_SOFT:
4227                 break;
4228         }
4229
4230         r_numqueries = 0;
4231         r_maxqueries = 0;
4232         memset(r_queries, 0, sizeof(r_queries));
4233
4234         r_qwskincache = NULL;
4235         r_qwskincache_size = 0;
4236
4237         // clear out the r_skinframe state
4238         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4239         memset(&r_skinframe, 0, sizeof(r_skinframe));
4240
4241         if (r_svbsp.nodes)
4242                 Mem_Free(r_svbsp.nodes);
4243         memset(&r_svbsp, 0, sizeof (r_svbsp));
4244         R_FreeTexturePool(&r_main_texturepool);
4245         loadingscreentexture = NULL;
4246         r_texture_blanknormalmap = NULL;
4247         r_texture_white = NULL;
4248         r_texture_grey128 = NULL;
4249         r_texture_black = NULL;
4250         r_texture_whitecube = NULL;
4251         r_texture_normalizationcube = NULL;
4252         r_texture_fogattenuation = NULL;
4253         r_texture_fogheighttexture = NULL;
4254         r_texture_gammaramps = NULL;
4255         r_texture_numcubemaps = 0;
4256         //r_texture_fogintensity = NULL;
4257         memset(&r_fb, 0, sizeof(r_fb));
4258         R_GLSL_Restart_f();
4259
4260         r_glsl_permutation = NULL;
4261         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4262         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4263 #ifdef SUPPORTD3D
4264         r_hlsl_permutation = NULL;
4265         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4266         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4267 #endif
4268 }
4269
4270 static void gl_main_newmap(void)
4271 {
4272         // FIXME: move this code to client
4273         char *entities, entname[MAX_QPATH];
4274         if (r_qwskincache)
4275                 Mem_Free(r_qwskincache);
4276         r_qwskincache = NULL;
4277         r_qwskincache_size = 0;
4278         if (cl.worldmodel)
4279         {
4280                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4281                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4282                 {
4283                         CL_ParseEntityLump(entities);
4284                         Mem_Free(entities);
4285                         return;
4286                 }
4287                 if (cl.worldmodel->brush.entities)
4288                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4289         }
4290         R_Main_FreeViewCache();
4291
4292         R_FrameData_Reset();
4293         R_BufferData_Reset();
4294 }
4295
4296 void GL_Main_Init(void)
4297 {
4298         int i;
4299         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4300         R_InitShaderModeInfo();
4301
4302         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4303         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4304         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4305         if (gamemode == GAME_NEHAHRA)
4306         {
4307                 Cvar_RegisterVariable (&gl_fogenable);
4308                 Cvar_RegisterVariable (&gl_fogdensity);
4309                 Cvar_RegisterVariable (&gl_fogred);
4310                 Cvar_RegisterVariable (&gl_foggreen);
4311                 Cvar_RegisterVariable (&gl_fogblue);
4312                 Cvar_RegisterVariable (&gl_fogstart);
4313                 Cvar_RegisterVariable (&gl_fogend);
4314                 Cvar_RegisterVariable (&gl_skyclip);
4315         }
4316         Cvar_RegisterVariable(&r_motionblur);
4317         Cvar_RegisterVariable(&r_damageblur);
4318         Cvar_RegisterVariable(&r_motionblur_averaging);
4319         Cvar_RegisterVariable(&r_motionblur_randomize);
4320         Cvar_RegisterVariable(&r_motionblur_minblur);
4321         Cvar_RegisterVariable(&r_motionblur_maxblur);
4322         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4323         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4324         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4325         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4326         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4327         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4328         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4329         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4330         Cvar_RegisterVariable(&r_equalize_entities_by);
4331         Cvar_RegisterVariable(&r_equalize_entities_to);
4332         Cvar_RegisterVariable(&r_depthfirst);
4333         Cvar_RegisterVariable(&r_useinfinitefarclip);
4334         Cvar_RegisterVariable(&r_farclip_base);
4335         Cvar_RegisterVariable(&r_farclip_world);
4336         Cvar_RegisterVariable(&r_nearclip);
4337         Cvar_RegisterVariable(&r_deformvertexes);
4338         Cvar_RegisterVariable(&r_transparent);
4339         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4340         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4341         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4342         Cvar_RegisterVariable(&r_showoverdraw);
4343         Cvar_RegisterVariable(&r_showbboxes);
4344         Cvar_RegisterVariable(&r_showbboxes_client);
4345         Cvar_RegisterVariable(&r_showsurfaces);
4346         Cvar_RegisterVariable(&r_showtris);
4347         Cvar_RegisterVariable(&r_shownormals);
4348         Cvar_RegisterVariable(&r_showlighting);
4349         Cvar_RegisterVariable(&r_showshadowvolumes);
4350         Cvar_RegisterVariable(&r_showcollisionbrushes);
4351         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4352         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4353         Cvar_RegisterVariable(&r_showdisabledepthtest);
4354         Cvar_RegisterVariable(&r_drawportals);
4355         Cvar_RegisterVariable(&r_drawentities);
4356         Cvar_RegisterVariable(&r_draw2d);
4357         Cvar_RegisterVariable(&r_drawworld);
4358         Cvar_RegisterVariable(&r_cullentities_trace);
4359         Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4360         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4361         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4362         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4363         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4364         Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4365         Cvar_RegisterVariable(&r_sortentities);
4366         Cvar_RegisterVariable(&r_drawviewmodel);
4367         Cvar_RegisterVariable(&r_drawexteriormodel);
4368         Cvar_RegisterVariable(&r_speeds);
4369         Cvar_RegisterVariable(&r_fullbrights);
4370         Cvar_RegisterVariable(&r_wateralpha);
4371         Cvar_RegisterVariable(&r_dynamic);
4372         Cvar_RegisterVariable(&r_fakelight);
4373         Cvar_RegisterVariable(&r_fakelight_intensity);
4374         Cvar_RegisterVariable(&r_fullbright);
4375         Cvar_RegisterVariable(&r_shadows);
4376         Cvar_RegisterVariable(&r_shadows_darken);
4377         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4378         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4379         Cvar_RegisterVariable(&r_shadows_throwdistance);
4380         Cvar_RegisterVariable(&r_shadows_throwdirection);
4381         Cvar_RegisterVariable(&r_shadows_focus);
4382         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4383         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4384         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4385         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4386         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4387         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4388         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4389         Cvar_RegisterVariable(&r_fog_exp2);
4390         Cvar_RegisterVariable(&r_fog_clear);
4391         Cvar_RegisterVariable(&r_drawfog);
4392         Cvar_RegisterVariable(&r_transparentdepthmasking);
4393         Cvar_RegisterVariable(&r_transparent_sortmindist);
4394         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4395         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4396         Cvar_RegisterVariable(&r_texture_dds_load);
4397         Cvar_RegisterVariable(&r_texture_dds_save);
4398         Cvar_RegisterVariable(&r_textureunits);
4399         Cvar_RegisterVariable(&gl_combine);
4400         Cvar_RegisterVariable(&r_usedepthtextures);
4401         Cvar_RegisterVariable(&r_viewfbo);
4402         Cvar_RegisterVariable(&r_viewscale);
4403         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4404         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4405         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4406         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4407         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4408         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4409         Cvar_RegisterVariable(&r_glsl);
4410         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4411         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4412         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4413         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4414         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4415         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4416         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4417         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4418         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4419         Cvar_RegisterVariable(&r_glsl_postprocess);
4420         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4421         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4422         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4423         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4424         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4425         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4427         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4428         Cvar_RegisterVariable(&r_celshading);
4429         Cvar_RegisterVariable(&r_celoutlines);
4430
4431         Cvar_RegisterVariable(&r_water);
4432         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4433         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4434         Cvar_RegisterVariable(&r_water_clippingplanebias);
4435         Cvar_RegisterVariable(&r_water_refractdistort);
4436         Cvar_RegisterVariable(&r_water_reflectdistort);
4437         Cvar_RegisterVariable(&r_water_scissormode);
4438         Cvar_RegisterVariable(&r_water_lowquality);
4439         Cvar_RegisterVariable(&r_water_hideplayer);
4440         Cvar_RegisterVariable(&r_water_fbo);
4441
4442         Cvar_RegisterVariable(&r_lerpsprites);
4443         Cvar_RegisterVariable(&r_lerpmodels);
4444         Cvar_RegisterVariable(&r_lerplightstyles);
4445         Cvar_RegisterVariable(&r_waterscroll);
4446         Cvar_RegisterVariable(&r_bloom);
4447         Cvar_RegisterVariable(&r_bloom_colorscale);
4448         Cvar_RegisterVariable(&r_bloom_brighten);
4449         Cvar_RegisterVariable(&r_bloom_blur);
4450         Cvar_RegisterVariable(&r_bloom_resolution);
4451         Cvar_RegisterVariable(&r_bloom_colorexponent);
4452         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4453         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4454         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4455         Cvar_RegisterVariable(&r_hdr_glowintensity);
4456         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4457         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4458         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4459         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4460         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4461         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4462         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4463         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4464         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4465         Cvar_RegisterVariable(&developer_texturelogging);
4466         Cvar_RegisterVariable(&gl_lightmaps);
4467         Cvar_RegisterVariable(&r_test);
4468         Cvar_RegisterVariable(&r_batch_multidraw);
4469         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4470         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4471         Cvar_RegisterVariable(&r_glsl_skeletal);
4472         Cvar_RegisterVariable(&r_glsl_saturation);
4473         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4474         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4475         Cvar_RegisterVariable(&r_framedatasize);
4476         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4477                 Cvar_RegisterVariable(&r_buffermegs[i]);
4478         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4479         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4480                 Cvar_SetValue("r_fullbrights", 0);
4481 #ifdef DP_MOBILETOUCH
4482         // GLES devices have terrible depth precision in general, so...
4483         Cvar_SetValueQuick(&r_nearclip, 4);
4484         Cvar_SetValueQuick(&r_farclip_base, 4096);
4485         Cvar_SetValueQuick(&r_farclip_world, 0);
4486         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4487 #endif
4488         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4489 }
4490
4491 void Render_Init(void)
4492 {
4493         gl_backend_init();
4494         R_Textures_Init();
4495         GL_Main_Init();
4496         Font_Init();
4497         GL_Draw_Init();
4498         R_Shadow_Init();
4499         R_Sky_Init();
4500         GL_Surf_Init();
4501         Sbar_Init();
4502         R_Particles_Init();
4503         R_Explosion_Init();
4504         R_LightningBeams_Init();
4505         Mod_RenderInit();
4506 }
4507
4508 /*
4509 ===============
4510 GL_Init
4511 ===============
4512 */
4513 #ifndef USE_GLES2
4514 extern char *ENGINE_EXTENSIONS;
4515 void GL_Init (void)
4516 {
4517         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4518         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4519         gl_version = (const char *)qglGetString(GL_VERSION);
4520         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4521
4522         if (!gl_extensions)
4523                 gl_extensions = "";
4524         if (!gl_platformextensions)
4525                 gl_platformextensions = "";
4526
4527         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4528         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4529         Con_Printf("GL_VERSION: %s\n", gl_version);
4530         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4531         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4532
4533         VID_CheckExtensions();
4534
4535         // LordHavoc: report supported extensions
4536 #ifdef CONFIG_MENU
4537         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4538 #else
4539         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4540 #endif
4541
4542         // clear to black (loading plaque will be seen over this)
4543         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4544 }
4545 #endif
4546
4547 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4548 {
4549         int i;
4550         mplane_t *p;
4551         if (r_trippy.integer)
4552                 return false;
4553         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4554         {
4555                 p = r_refdef.view.frustum + i;
4556                 switch(p->signbits)
4557                 {
4558                 default:
4559                 case 0:
4560                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4561                                 return true;
4562                         break;
4563                 case 1:
4564                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4565                                 return true;
4566                         break;
4567                 case 2:
4568                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4569                                 return true;
4570                         break;
4571                 case 3:
4572                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4573                                 return true;
4574                         break;
4575                 case 4:
4576                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4577                                 return true;
4578                         break;
4579                 case 5:
4580                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4581                                 return true;
4582                         break;
4583                 case 6:
4584                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4585                                 return true;
4586                         break;
4587                 case 7:
4588                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4589                                 return true;
4590                         break;
4591                 }
4592         }
4593         return false;
4594 }
4595
4596 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4597 {
4598         int i;
4599         const mplane_t *p;
4600         if (r_trippy.integer)
4601                 return false;
4602         for (i = 0;i < numplanes;i++)
4603         {
4604                 p = planes + i;
4605                 switch(p->signbits)
4606                 {
4607                 default:
4608                 case 0:
4609                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4610                                 return true;
4611                         break;
4612                 case 1:
4613                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4614                                 return true;
4615                         break;
4616                 case 2:
4617                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4618                                 return true;
4619                         break;
4620                 case 3:
4621                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4622                                 return true;
4623                         break;
4624                 case 4:
4625                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4626                                 return true;
4627                         break;
4628                 case 5:
4629                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4630                                 return true;
4631                         break;
4632                 case 6:
4633                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4634                                 return true;
4635                         break;
4636                 case 7:
4637                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4638                                 return true;
4639                         break;
4640                 }
4641         }
4642         return false;
4643 }
4644
4645 //==================================================================================
4646
4647 // LordHavoc: this stores temporary data used within the same frame
4648
4649 typedef struct r_framedata_mem_s
4650 {
4651         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4652         size_t size; // how much usable space
4653         size_t current; // how much space in use
4654         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4655         size_t wantedsize; // how much space was allocated
4656         unsigned char *data; // start of real data (16byte aligned)
4657 }
4658 r_framedata_mem_t;
4659
4660 static r_framedata_mem_t *r_framedata_mem;
4661
4662 void R_FrameData_Reset(void)
4663 {
4664         while (r_framedata_mem)
4665         {
4666                 r_framedata_mem_t *next = r_framedata_mem->purge;
4667                 Mem_Free(r_framedata_mem);
4668                 r_framedata_mem = next;
4669         }
4670 }
4671
4672 static void R_FrameData_Resize(qboolean mustgrow)
4673 {
4674         size_t wantedsize;
4675         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4676         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4677         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4678         {
4679                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4680                 newmem->wantedsize = wantedsize;
4681                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4682                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4683                 newmem->current = 0;
4684                 newmem->mark = 0;
4685                 newmem->purge = r_framedata_mem;
4686                 r_framedata_mem = newmem;
4687         }
4688 }
4689
4690 void R_FrameData_NewFrame(void)
4691 {
4692         R_FrameData_Resize(false);
4693         if (!r_framedata_mem)
4694                 return;
4695         // if we ran out of space on the last frame, free the old memory now
4696         while (r_framedata_mem->purge)
4697         {
4698                 // repeatedly remove the second item in the list, leaving only head
4699                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4700                 Mem_Free(r_framedata_mem->purge);
4701                 r_framedata_mem->purge = next;
4702         }
4703         // reset the current mem pointer
4704         r_framedata_mem->current = 0;
4705         r_framedata_mem->mark = 0;
4706 }
4707
4708 void *R_FrameData_Alloc(size_t size)
4709 {
4710         void *data;
4711         float newvalue;
4712
4713         // align to 16 byte boundary - the data pointer is already aligned, so we
4714         // only need to ensure the size of every allocation is also aligned
4715         size = (size + 15) & ~15;
4716
4717         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4718         {
4719                 // emergency - we ran out of space, allocate more memory
4720                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4721                 newvalue = r_framedatasize.value * 2.0f;
4722                 // 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
4723                 if (sizeof(size_t) >= 8)
4724                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4725                 else
4726                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4727                 // this might not be a growing it, but we'll allocate another buffer every time
4728                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4729                 R_FrameData_Resize(true);
4730         }
4731
4732         data = r_framedata_mem->data + r_framedata_mem->current;
4733         r_framedata_mem->current += size;
4734
4735         // count the usage for stats
4736         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4737         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4738
4739         return (void *)data;
4740 }
4741
4742 void *R_FrameData_Store(size_t size, void *data)
4743 {
4744         void *d = R_FrameData_Alloc(size);
4745         if (d && data)
4746                 memcpy(d, data, size);
4747         return d;
4748 }
4749
4750 void R_FrameData_SetMark(void)
4751 {
4752         if (!r_framedata_mem)
4753                 return;
4754         r_framedata_mem->mark = r_framedata_mem->current;
4755 }
4756
4757 void R_FrameData_ReturnToMark(void)
4758 {
4759         if (!r_framedata_mem)
4760                 return;
4761         r_framedata_mem->current = r_framedata_mem->mark;
4762 }
4763
4764 //==================================================================================
4765
4766 // avoid reusing the same buffer objects on consecutive frames
4767 #define R_BUFFERDATA_CYCLE 3
4768
4769 typedef struct r_bufferdata_buffer_s
4770 {
4771         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4772         size_t size; // how much usable space
4773         size_t current; // how much space in use
4774         r_meshbuffer_t *buffer; // the buffer itself
4775 }
4776 r_bufferdata_buffer_t;
4777
4778 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4779 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4780
4781 /// frees all dynamic buffers
4782 void R_BufferData_Reset(void)
4783 {
4784         int cycle, type;
4785         r_bufferdata_buffer_t **p, *mem;
4786         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4787         {
4788                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4789                 {
4790                         // free all buffers
4791                         p = &r_bufferdata_buffer[cycle][type];
4792                         while (*p)
4793                         {
4794                                 mem = *p;
4795                                 *p = (*p)->purge;
4796                                 if (mem->buffer)
4797                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4798                                 Mem_Free(mem);
4799                         }
4800                 }
4801         }
4802 }
4803
4804 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4805 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4806 {
4807         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4808         size_t size;
4809         float newvalue = r_buffermegs[type].value;
4810
4811         // increase the cvar if we have to (but only if we already have a mem)
4812         if (mustgrow && mem)
4813                 newvalue *= 2.0f;
4814         newvalue = bound(0.25f, newvalue, 256.0f);
4815         while (newvalue * 1024*1024 < minsize)
4816                 newvalue *= 2.0f;
4817
4818         // clamp the cvar to valid range
4819         newvalue = bound(0.25f, newvalue, 256.0f);
4820         if (r_buffermegs[type].value != newvalue)
4821                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4822
4823         // calculate size in bytes
4824         size = (size_t)(newvalue * 1024*1024);
4825         size = bound(131072, size, 256*1024*1024);
4826
4827         // allocate a new buffer if the size is different (purge old one later)
4828         // or if we were told we must grow the buffer
4829         if (!mem || mem->size != size || mustgrow)
4830         {
4831                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4832                 mem->size = size;
4833                 mem->current = 0;
4834                 if (type == R_BUFFERDATA_VERTEX)
4835                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4836                 else if (type == R_BUFFERDATA_INDEX16)
4837                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4838                 else if (type == R_BUFFERDATA_INDEX32)
4839                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4840                 else if (type == R_BUFFERDATA_UNIFORM)
4841                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4842                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4843                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4844         }
4845 }
4846
4847 void R_BufferData_NewFrame(void)
4848 {
4849         int type;
4850         r_bufferdata_buffer_t **p, *mem;
4851         // cycle to the next frame's buffers
4852         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4853         // if we ran out of space on the last time we used these buffers, free the old memory now
4854         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4855         {
4856                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4857                 {
4858                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4859                         // free all but the head buffer, this is how we recycle obsolete
4860                         // buffers after they are no longer in use
4861                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4862                         while (*p)
4863                         {
4864                                 mem = *p;
4865                                 *p = (*p)->purge;
4866                                 if (mem->buffer)
4867                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4868                                 Mem_Free(mem);
4869                         }
4870                         // reset the current offset
4871                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4872                 }
4873         }
4874 }
4875
4876 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4877 {
4878         r_bufferdata_buffer_t *mem;
4879         int offset = 0;
4880         int padsize;
4881
4882         *returnbufferoffset = 0;
4883
4884         // align size to a byte boundary appropriate for the buffer type, this
4885         // makes all allocations have aligned start offsets
4886         if (type == R_BUFFERDATA_UNIFORM)
4887                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4888         else
4889                 padsize = (datasize + 15) & ~15;
4890
4891         // if we ran out of space in this buffer we must allocate a new one
4892         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)
4893                 R_BufferData_Resize(type, true, padsize);
4894
4895         // if the resize did not give us enough memory, fail
4896         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)
4897                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4898
4899         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4900         offset = (int)mem->current;
4901         mem->current += padsize;
4902
4903         // upload the data to the buffer at the chosen offset
4904         if (offset == 0)
4905                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4906         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4907
4908         // count the usage for stats
4909         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4910         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4911
4912         // return the buffer offset
4913         *returnbufferoffset = offset;
4914
4915         return mem->buffer;
4916 }
4917
4918 //==================================================================================
4919
4920 // LordHavoc: animcache originally written by Echon, rewritten since then
4921
4922 /**
4923  * Animation cache prevents re-generating mesh data for an animated model
4924  * multiple times in one frame for lighting, shadowing, reflections, etc.
4925  */
4926
4927 void R_AnimCache_Free(void)
4928 {
4929 }
4930
4931 void R_AnimCache_ClearCache(void)
4932 {
4933         int i;
4934         entity_render_t *ent;
4935
4936         for (i = 0;i < r_refdef.scene.numentities;i++)
4937         {
4938                 ent = r_refdef.scene.entities[i];
4939                 ent->animcache_vertex3f = NULL;
4940                 ent->animcache_vertex3f_vertexbuffer = NULL;
4941                 ent->animcache_vertex3f_bufferoffset = 0;
4942                 ent->animcache_normal3f = NULL;
4943                 ent->animcache_normal3f_vertexbuffer = NULL;
4944                 ent->animcache_normal3f_bufferoffset = 0;
4945                 ent->animcache_svector3f = NULL;
4946                 ent->animcache_svector3f_vertexbuffer = NULL;
4947                 ent->animcache_svector3f_bufferoffset = 0;
4948                 ent->animcache_tvector3f = NULL;
4949                 ent->animcache_tvector3f_vertexbuffer = NULL;
4950                 ent->animcache_tvector3f_bufferoffset = 0;
4951                 ent->animcache_vertexmesh = NULL;
4952                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4953                 ent->animcache_vertexmesh_bufferoffset = 0;
4954                 ent->animcache_skeletaltransform3x4 = NULL;
4955                 ent->animcache_skeletaltransform3x4buffer = NULL;
4956                 ent->animcache_skeletaltransform3x4offset = 0;
4957                 ent->animcache_skeletaltransform3x4size = 0;
4958         }
4959 }
4960
4961 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4962 {
4963         int i;
4964
4965         // check if we need the meshbuffers
4966         if (!vid.useinterleavedarrays)
4967                 return;
4968
4969         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4970                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4971         // TODO: upload vertexbuffer?
4972         if (ent->animcache_vertexmesh)
4973         {
4974                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4975                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4976                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4977                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4978                 for (i = 0;i < numvertices;i++)
4979                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4980                 if (ent->animcache_svector3f)
4981                         for (i = 0;i < numvertices;i++)
4982                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4983                 if (ent->animcache_tvector3f)
4984                         for (i = 0;i < numvertices;i++)
4985                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4986                 if (ent->animcache_normal3f)
4987                         for (i = 0;i < numvertices;i++)
4988                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4989         }
4990 }
4991
4992 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4993 {
4994         dp_model_t *model = ent->model;
4995         int numvertices;
4996
4997         // see if this ent is worth caching
4998         if (!model || !model->Draw || !model->AnimateVertices)
4999                 return false;
5000         // nothing to cache if it contains no animations and has no skeleton
5001         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5002                 return false;
5003         // see if it is already cached for gpuskeletal
5004         if (ent->animcache_skeletaltransform3x4)
5005                 return false;
5006         // see if it is already cached as a mesh
5007         if (ent->animcache_vertex3f)
5008         {
5009                 // check if we need to add normals or tangents
5010                 if (ent->animcache_normal3f)
5011                         wantnormals = false;
5012                 if (ent->animcache_svector3f)
5013                         wanttangents = false;
5014                 if (!wantnormals && !wanttangents)
5015                         return false;
5016         }
5017
5018         // check which kind of cache we need to generate
5019         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5020         {
5021                 // cache the skeleton so the vertex shader can use it
5022                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5023                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5024                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5025                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5026                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5027                 // note: this can fail if the buffer is at the grow limit
5028                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5029                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5030         }
5031         else if (ent->animcache_vertex3f)
5032         {
5033                 // mesh was already cached but we may need to add normals/tangents
5034                 // (this only happens with multiple views, reflections, cameras, etc)
5035                 if (wantnormals || wanttangents)
5036                 {
5037                         numvertices = model->surfmesh.num_vertices;
5038                         if (wantnormals)
5039                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5040                         if (wanttangents)
5041                         {
5042                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5043                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5044                         }
5045                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5046                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5047                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5048                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5049                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5050                 }
5051         }
5052         else
5053         {
5054                 // generate mesh cache
5055                 numvertices = model->surfmesh.num_vertices;
5056                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5057                 if (wantnormals)
5058                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5059                 if (wanttangents)
5060                 {
5061                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5062                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5063                 }
5064                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5065                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5066                 if (wantnormals || wanttangents)
5067                 {
5068                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5069                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5070                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5071                 }
5072                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5073                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5074                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5075         }
5076         return true;
5077 }
5078
5079 void R_AnimCache_CacheVisibleEntities(void)
5080 {
5081         int i;
5082         qboolean wantnormals = true;
5083         qboolean wanttangents = !r_showsurfaces.integer;
5084
5085         switch(vid.renderpath)
5086         {
5087         case RENDERPATH_GL20:
5088         case RENDERPATH_D3D9:
5089         case RENDERPATH_D3D10:
5090         case RENDERPATH_D3D11:
5091         case RENDERPATH_GLES2:
5092                 break;
5093         case RENDERPATH_GL11:
5094         case RENDERPATH_GL13:
5095         case RENDERPATH_GLES1:
5096                 wanttangents = false;
5097                 break;
5098         case RENDERPATH_SOFT:
5099                 break;
5100         }
5101
5102         if (r_shownormals.integer)
5103                 wanttangents = wantnormals = true;
5104
5105         // TODO: thread this
5106         // NOTE: R_PrepareRTLights() also caches entities
5107
5108         for (i = 0;i < r_refdef.scene.numentities;i++)
5109                 if (r_refdef.viewcache.entityvisible[i])
5110                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5111 }
5112
5113 //==================================================================================
5114
5115 extern cvar_t r_overheadsprites_pushback;
5116
5117 static void R_View_UpdateEntityLighting (void)
5118 {
5119         int i;
5120         entity_render_t *ent;
5121         vec3_t tempdiffusenormal, avg;
5122         vec_t f, fa, fd, fdd;
5123         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5124
5125         for (i = 0;i < r_refdef.scene.numentities;i++)
5126         {
5127                 ent = r_refdef.scene.entities[i];
5128
5129                 // skip unseen models
5130                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5131                         continue;
5132
5133                 // skip bsp models
5134                 if (ent->model && ent->model == cl.worldmodel)
5135                 {
5136                         // TODO: use modellight for r_ambient settings on world?
5137                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5138                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5139                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5140                         continue;
5141                 }
5142                 
5143                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5144                 {
5145                         // aleady updated by CSQC
5146                         // TODO: force modellight on BSP models in this case?
5147                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5148                 }
5149                 else
5150                 {
5151                         // fetch the lighting from the worldmodel data
5152                         VectorClear(ent->modellight_ambient);
5153                         VectorClear(ent->modellight_diffuse);
5154                         VectorClear(tempdiffusenormal);
5155                         if (ent->flags & RENDER_LIGHT)
5156                         {
5157                                 vec3_t org;
5158                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5159
5160                                 // complete lightning for lit sprites
5161                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5162                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5163                                 {
5164                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5165                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5166                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5167                                 }
5168                                 else
5169                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5170
5171                                 if(ent->flags & RENDER_EQUALIZE)
5172                                 {
5173                                         // first fix up ambient lighting...
5174                                         if(r_equalize_entities_minambient.value > 0)
5175                                         {
5176                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5177                                                 if(fd > 0)
5178                                                 {
5179                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5180                                                         if(fa < r_equalize_entities_minambient.value * fd)
5181                                                         {
5182                                                                 // solve:
5183                                                                 //   fa'/fd' = minambient
5184                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5185                                                                 //   ...
5186                                                                 //   fa' = fd' * minambient
5187                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5188                                                                 //   ...
5189                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5190                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5191                                                                 //   ...
5192                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5193                                                                 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5194                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5195                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5196                                                         }
5197                                                 }
5198                                         }
5199
5200                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5201                                         {
5202                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5203                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5204                                                 f = fa + 0.25 * fd;
5205                                                 if(f > 0)
5206                                                 {
5207                                                         // adjust brightness and saturation to target
5208                                                         avg[0] = avg[1] = avg[2] = fa / f;
5209                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5210                                                         avg[0] = avg[1] = avg[2] = fd / f;
5211                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5212                                                 }
5213                                         }
5214                                 }
5215                         }
5216                         else // highly rare
5217                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5218                 }
5219
5220                 // move the light direction into modelspace coordinates for lighting code
5221                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5222                 if(VectorLength2(ent->modellight_lightdir) == 0)
5223                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5224                 VectorNormalize(ent->modellight_lightdir);
5225         }
5226 }
5227
5228 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5229 {
5230         int i;
5231         vec3_t eyemins, eyemaxs;
5232         vec3_t boxmins, boxmaxs;
5233         vec3_t start;
5234         vec3_t end;
5235         dp_model_t *model = r_refdef.scene.worldmodel;
5236         static vec3_t positions[] = {
5237                 { 0.5f, 0.5f, 0.5f },
5238                 { 0.0f, 0.0f, 0.0f },
5239                 { 0.0f, 0.0f, 1.0f },
5240                 { 0.0f, 1.0f, 0.0f },
5241                 { 0.0f, 1.0f, 1.0f },
5242                 { 1.0f, 0.0f, 0.0f },
5243                 { 1.0f, 0.0f, 1.0f },
5244                 { 1.0f, 1.0f, 0.0f },
5245                 { 1.0f, 1.0f, 1.0f },
5246         };
5247
5248         // sample count can be set to -1 to skip this logic, for flicker-prone objects
5249         if (numsamples < 0)
5250                 return true;
5251
5252         // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5253         if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5254                 return true;
5255
5256         if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5257                 return true;
5258
5259         // expand the eye box a little
5260         eyemins[0] = eye[0] - eyejitter;
5261         eyemaxs[0] = eye[0] + eyejitter;
5262         eyemins[1] = eye[1] - eyejitter;
5263         eyemaxs[1] = eye[1] + eyejitter;
5264         eyemins[2] = eye[2] - eyejitter;
5265         eyemaxs[2] = eye[2] + eyejitter;
5266         // expand the box a little
5267         boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5268         boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5269         boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5270         boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5271         boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5272         boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5273
5274         // return true if eye overlaps enlarged box
5275         if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5276                 return true;
5277
5278         // try specific positions in the box first - note that these can be cached
5279         if (r_cullentities_trace_entityocclusion.integer)
5280         {
5281                 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5282                 {
5283                         VectorCopy(eye, start);
5284                         end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5285                         end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5286                         end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5287                         //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5288                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5289                         // not picky - if the trace ended anywhere in the box we're good
5290                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5291                                 return true;
5292                 }
5293         }
5294         else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5295                 return true;
5296
5297         // try various random positions
5298         for (i = 0; i < numsamples; i++)
5299         {
5300                 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5301                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5302                 if (r_cullentities_trace_entityocclusion.integer)
5303                 {
5304                         trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5305                         // not picky - if the trace ended anywhere in the box we're good
5306                         if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5307                                 return true;
5308                 }
5309                 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5310                         return true;
5311         }
5312
5313         return false;
5314 }
5315
5316
5317 static void R_View_UpdateEntityVisible (void)
5318 {
5319         int i;
5320         int renderimask;
5321         int samples;
5322         entity_render_t *ent;
5323
5324         if (r_refdef.envmap || r_fb.water.hideplayer)
5325                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5326         else if (chase_active.integer || r_fb.water.renderingscene)
5327                 renderimask = RENDER_VIEWMODEL;
5328         else
5329                 renderimask = RENDER_EXTERIORMODEL;
5330         if (!r_drawviewmodel.integer)
5331                 renderimask |= RENDER_VIEWMODEL;
5332         if (!r_drawexteriormodel.integer)
5333                 renderimask |= RENDER_EXTERIORMODEL;
5334         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5335         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5336         {
5337                 // worldmodel can check visibility
5338                 for (i = 0;i < r_refdef.scene.numentities;i++)
5339                 {
5340                         ent = r_refdef.scene.entities[i];
5341                         if (!(ent->flags & renderimask))
5342                         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)))
5343                         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))
5344                                 r_refdef.viewcache.entityvisible[i] = true;
5345                 }
5346         }
5347         else
5348         {
5349                 // no worldmodel or it can't check visibility
5350                 for (i = 0;i < r_refdef.scene.numentities;i++)
5351                 {
5352                         ent = r_refdef.scene.entities[i];
5353                         if (!(ent->flags & renderimask))
5354                         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)))
5355                                 r_refdef.viewcache.entityvisible[i] = true;
5356                 }
5357         }
5358         if (r_cullentities_trace.integer)
5359         {
5360                 for (i = 0;i < r_refdef.scene.numentities;i++)
5361                 {
5362                         if (!r_refdef.viewcache.entityvisible[i])
5363                                 continue;
5364                         ent = r_refdef.scene.entities[i];
5365                         if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5366                         {
5367                                 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5368                                 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5369                                         ent->last_trace_visibility = realtime;
5370                                 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5371                                         r_refdef.viewcache.entityvisible[i] = 0;
5372                         }
5373                 }
5374         }
5375 }
5376
5377 /// only used if skyrendermasked, and normally returns false
5378 static int R_DrawBrushModelsSky (void)
5379 {
5380         int i, sky;
5381         entity_render_t *ent;
5382
5383         sky = false;
5384         for (i = 0;i < r_refdef.scene.numentities;i++)
5385         {
5386                 if (!r_refdef.viewcache.entityvisible[i])
5387                         continue;
5388                 ent = r_refdef.scene.entities[i];
5389                 if (!ent->model || !ent->model->DrawSky)
5390                         continue;
5391                 ent->model->DrawSky(ent);
5392                 sky = true;
5393         }
5394         return sky;
5395 }
5396
5397 static void R_DrawNoModel(entity_render_t *ent);
5398 static void R_DrawModels(void)
5399 {
5400         int i;
5401         entity_render_t *ent;
5402
5403         for (i = 0;i < r_refdef.scene.numentities;i++)
5404         {
5405                 if (!r_refdef.viewcache.entityvisible[i])
5406                         continue;
5407                 ent = r_refdef.scene.entities[i];
5408                 r_refdef.stats[r_stat_entities]++;
5409                 /*
5410                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5411                 {
5412                         vec3_t f, l, u, o;
5413                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5414                         Con_Printf("R_DrawModels\n");
5415                         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]);
5416                         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);
5417                         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);
5418                 }
5419                 */
5420                 if (ent->model && ent->model->Draw != NULL)
5421                         ent->model->Draw(ent);
5422                 else
5423                         R_DrawNoModel(ent);
5424         }
5425 }
5426
5427 static void R_DrawModelsDepth(void)
5428 {
5429         int i;
5430         entity_render_t *ent;
5431
5432         for (i = 0;i < r_refdef.scene.numentities;i++)
5433         {
5434                 if (!r_refdef.viewcache.entityvisible[i])
5435                         continue;
5436                 ent = r_refdef.scene.entities[i];
5437                 if (ent->model && ent->model->DrawDepth != NULL)
5438                         ent->model->DrawDepth(ent);
5439         }
5440 }
5441
5442 static void R_DrawModelsDebug(void)
5443 {
5444         int i;
5445         entity_render_t *ent;
5446
5447         for (i = 0;i < r_refdef.scene.numentities;i++)
5448         {
5449                 if (!r_refdef.viewcache.entityvisible[i])
5450                         continue;
5451                 ent = r_refdef.scene.entities[i];
5452                 if (ent->model && ent->model->DrawDebug != NULL)
5453                         ent->model->DrawDebug(ent);
5454         }
5455 }
5456
5457 static void R_DrawModelsAddWaterPlanes(void)
5458 {
5459         int i;
5460         entity_render_t *ent;
5461
5462         for (i = 0;i < r_refdef.scene.numentities;i++)
5463         {
5464                 if (!r_refdef.viewcache.entityvisible[i])
5465                         continue;
5466                 ent = r_refdef.scene.entities[i];
5467                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5468                         ent->model->DrawAddWaterPlanes(ent);
5469         }
5470 }
5471
5472 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}};
5473
5474 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5475 {
5476         if (r_hdr_irisadaptation.integer)
5477         {
5478                 vec3_t p;
5479                 vec3_t ambient;
5480                 vec3_t diffuse;
5481                 vec3_t diffusenormal;
5482                 vec3_t forward;
5483                 vec_t brightness = 0.0f;
5484                 vec_t goal;
5485                 vec_t current;
5486                 vec_t d;
5487                 int c;
5488                 VectorCopy(r_refdef.view.forward, forward);
5489                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5490                 {
5491                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5492                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5493                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5494                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5495                         d = DotProduct(forward, diffusenormal);
5496                         brightness += VectorLength(ambient);
5497                         if (d > 0)
5498                                 brightness += d * VectorLength(diffuse);
5499                 }
5500                 brightness *= 1.0f / c;
5501                 brightness += 0.00001f; // make sure it's never zero
5502                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5503                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5504                 current = r_hdr_irisadaptation_value.value;
5505                 if (current < goal)
5506                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5507                 else if (current > goal)
5508                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5509                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5510                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5511         }
5512         else if (r_hdr_irisadaptation_value.value != 1.0f)
5513                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5514 }
5515
5516 static void R_View_SetFrustum(const int *scissor)
5517 {
5518         int i;
5519         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5520         vec3_t forward, left, up, origin, v;
5521
5522         if(scissor)
5523         {
5524                 // flipped x coordinates (because x points left here)
5525                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5526                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5527
5528                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5529                 switch(vid.renderpath)
5530                 {
5531                         case RENDERPATH_D3D9:
5532                         case RENDERPATH_D3D10:
5533                         case RENDERPATH_D3D11:
5534                                 // non-flipped y coordinates
5535                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5536                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5537                                 break;
5538                         case RENDERPATH_SOFT:
5539                         case RENDERPATH_GL11:
5540                         case RENDERPATH_GL13:
5541                         case RENDERPATH_GL20:
5542                         case RENDERPATH_GLES1:
5543                         case RENDERPATH_GLES2:
5544                                 // non-flipped y coordinates
5545                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5546                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5547                                 break;
5548                 }
5549         }
5550
5551         // we can't trust r_refdef.view.forward and friends in reflected scenes
5552         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5553
5554 #if 0
5555         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5556         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5557         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5558         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5559         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5560         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5561         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5562         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5563         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5564         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5565         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5566         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5567 #endif
5568
5569 #if 0
5570         zNear = r_refdef.nearclip;
5571         nudge = 1.0 - 1.0 / (1<<23);
5572         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5573         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5574         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5575         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5576         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5577         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5578         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5579         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5580 #endif
5581
5582
5583
5584 #if 0
5585         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5586         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5587         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5588         r_refdef.view.frustum[0].dist = m[15] - m[12];
5589
5590         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5591         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5592         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5593         r_refdef.view.frustum[1].dist = m[15] + m[12];
5594
5595         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5596         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5597         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5598         r_refdef.view.frustum[2].dist = m[15] - m[13];
5599
5600         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5601         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5602         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5603         r_refdef.view.frustum[3].dist = m[15] + m[13];
5604
5605         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5606         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5607         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5608         r_refdef.view.frustum[4].dist = m[15] - m[14];
5609
5610         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5611         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5612         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5613         r_refdef.view.frustum[5].dist = m[15] + m[14];
5614 #endif
5615
5616         if (r_refdef.view.useperspective)
5617         {
5618                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5619                 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]);
5620                 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]);
5621                 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]);
5622                 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]);
5623
5624                 // then the normals from the corners relative to origin
5625                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5626                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5627                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5628                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5629
5630                 // in a NORMAL view, forward cross left == up
5631                 // in a REFLECTED view, forward cross left == down
5632                 // so our cross products above need to be adjusted for a left handed coordinate system
5633                 CrossProduct(forward, left, v);
5634                 if(DotProduct(v, up) < 0)
5635                 {
5636                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5637                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5638                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5639                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5640                 }
5641
5642                 // Leaving those out was a mistake, those were in the old code, and they
5643                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5644                 // I couldn't reproduce it after adding those normalizations. --blub
5645                 VectorNormalize(r_refdef.view.frustum[0].normal);
5646                 VectorNormalize(r_refdef.view.frustum[1].normal);
5647                 VectorNormalize(r_refdef.view.frustum[2].normal);
5648                 VectorNormalize(r_refdef.view.frustum[3].normal);
5649
5650                 // make the corners absolute
5651                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5652                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5653                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5654                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5655
5656                 // one more normal
5657                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5658
5659                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5660                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5661                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5662                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5663                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5664         }
5665         else
5666         {
5667                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5668                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5669                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5670                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5671                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5672                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5673                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5674                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5675                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5676                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5677         }
5678         r_refdef.view.numfrustumplanes = 5;
5679
5680         if (r_refdef.view.useclipplane)
5681         {
5682                 r_refdef.view.numfrustumplanes = 6;
5683                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5684         }
5685
5686         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5687                 PlaneClassify(r_refdef.view.frustum + i);
5688
5689         // LordHavoc: note to all quake engine coders, Quake had a special case
5690         // for 90 degrees which assumed a square view (wrong), so I removed it,
5691         // Quake2 has it disabled as well.
5692
5693         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5694         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5695         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5696         //PlaneClassify(&frustum[0]);
5697
5698         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5699         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5700         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5701         //PlaneClassify(&frustum[1]);
5702
5703         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5704         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5705         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5706         //PlaneClassify(&frustum[2]);
5707
5708         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5709         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5710         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5711         //PlaneClassify(&frustum[3]);
5712
5713         // nearclip plane
5714         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5715         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5716         //PlaneClassify(&frustum[4]);
5717 }
5718
5719 static void R_View_UpdateWithScissor(const int *myscissor)
5720 {
5721         R_Main_ResizeViewCache();
5722         R_View_SetFrustum(myscissor);
5723         R_View_WorldVisibility(r_refdef.view.useclipplane);
5724         R_View_UpdateEntityVisible();
5725         R_View_UpdateEntityLighting();
5726 }
5727
5728 static void R_View_Update(void)
5729 {
5730         R_Main_ResizeViewCache();
5731         R_View_SetFrustum(NULL);
5732         R_View_WorldVisibility(r_refdef.view.useclipplane);
5733         R_View_UpdateEntityVisible();
5734         R_View_UpdateEntityLighting();
5735 }
5736
5737 float viewscalefpsadjusted = 1.0f;
5738
5739 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5740 {
5741         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5742         scale = bound(0.03125f, scale, 1.0f);
5743         *outwidth = (int)ceil(width * scale);
5744         *outheight = (int)ceil(height * scale);
5745 }
5746
5747 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5748 {
5749         const float *customclipplane = NULL;
5750         float plane[4];
5751         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5752         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5753         {
5754                 // LordHavoc: couldn't figure out how to make this approach the
5755                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5756                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5757                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5758                         dist = r_refdef.view.clipplane.dist;
5759                 plane[0] = r_refdef.view.clipplane.normal[0];
5760                 plane[1] = r_refdef.view.clipplane.normal[1];
5761                 plane[2] = r_refdef.view.clipplane.normal[2];
5762                 plane[3] = -dist;
5763                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5764         }
5765
5766         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5767         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5768
5769         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5770         if (!r_refdef.view.useperspective)
5771                 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);
5772         else if (vid.stencil && r_useinfinitefarclip.integer)
5773                 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);
5774         else
5775                 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);
5776         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5777         R_SetViewport(&r_refdef.view.viewport);
5778         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5779         {
5780                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5781                 float screenplane[4];
5782                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5783                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5784                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5785                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5786                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5787         }
5788 }
5789
5790 void R_EntityMatrix(const matrix4x4_t *matrix)
5791 {
5792         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5793         {
5794                 gl_modelmatrixchanged = false;
5795                 gl_modelmatrix = *matrix;
5796                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5797                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5798                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5799                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5800                 CHECKGLERROR
5801                 switch(vid.renderpath)
5802                 {
5803                 case RENDERPATH_D3D9:
5804 #ifdef SUPPORTD3D
5805                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5806                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5807 #endif
5808                         break;
5809                 case RENDERPATH_D3D10:
5810                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5811                         break;
5812                 case RENDERPATH_D3D11:
5813                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5814                         break;
5815                 case RENDERPATH_GL11:
5816                 case RENDERPATH_GL13:
5817                 case RENDERPATH_GLES1:
5818 #ifndef USE_GLES2
5819                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5820 #endif
5821                         break;
5822                 case RENDERPATH_SOFT:
5823                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5824                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5825                         break;
5826                 case RENDERPATH_GL20:
5827                 case RENDERPATH_GLES2:
5828                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5829                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5830                         break;
5831                 }
5832         }
5833 }
5834
5835 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5836 {
5837         r_viewport_t viewport;
5838
5839         CHECKGLERROR
5840
5841         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5842         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);
5843         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5844         R_SetViewport(&viewport);
5845         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5846         GL_Color(1, 1, 1, 1);
5847         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5848         GL_BlendFunc(GL_ONE, GL_ZERO);
5849         GL_ScissorTest(false);
5850         GL_DepthMask(false);
5851         GL_DepthRange(0, 1);
5852         GL_DepthTest(false);
5853         GL_DepthFunc(GL_LEQUAL);
5854         R_EntityMatrix(&identitymatrix);
5855         R_Mesh_ResetTextureState();
5856         GL_PolygonOffset(0, 0);
5857         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5858         switch(vid.renderpath)
5859         {
5860         case RENDERPATH_GL11:
5861         case RENDERPATH_GL13:
5862         case RENDERPATH_GL20:
5863         case RENDERPATH_GLES1:
5864         case RENDERPATH_GLES2:
5865                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5866                 break;
5867         case RENDERPATH_D3D9:
5868         case RENDERPATH_D3D10:
5869         case RENDERPATH_D3D11:
5870         case RENDERPATH_SOFT:
5871                 break;
5872         }
5873         GL_CullFace(GL_NONE);
5874
5875         CHECKGLERROR
5876 }
5877
5878 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5879 {
5880         DrawQ_Finish();
5881
5882         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5883 }
5884
5885 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5886 {
5887         DrawQ_Finish();
5888
5889         R_SetupView(true, fbo, depthtexture, colortexture);
5890         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5891         GL_Color(1, 1, 1, 1);
5892         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5893         GL_BlendFunc(GL_ONE, GL_ZERO);
5894         GL_ScissorTest(true);
5895         GL_DepthMask(true);
5896         GL_DepthRange(0, 1);
5897         GL_DepthTest(true);
5898         GL_DepthFunc(GL_LEQUAL);
5899         R_EntityMatrix(&identitymatrix);
5900         R_Mesh_ResetTextureState();
5901         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5902         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5903         switch(vid.renderpath)
5904         {
5905         case RENDERPATH_GL11:
5906         case RENDERPATH_GL13:
5907         case RENDERPATH_GL20:
5908         case RENDERPATH_GLES1:
5909         case RENDERPATH_GLES2:
5910                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5911                 break;
5912         case RENDERPATH_D3D9:
5913         case RENDERPATH_D3D10:
5914         case RENDERPATH_D3D11:
5915         case RENDERPATH_SOFT:
5916                 break;
5917         }
5918         GL_CullFace(r_refdef.view.cullface_back);
5919 }
5920
5921 /*
5922 ================
5923 R_RenderView_UpdateViewVectors
5924 ================
5925 */
5926 void R_RenderView_UpdateViewVectors(void)
5927 {
5928         // break apart the view matrix into vectors for various purposes
5929         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5930         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5931         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5932         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5933         // make an inverted copy of the view matrix for tracking sprites
5934         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5935 }
5936
5937 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5938 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5939
5940 static void R_Water_StartFrame(void)
5941 {
5942         int i;
5943         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5944         r_waterstate_waterplane_t *p;
5945         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;
5946
5947         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5948                 return;
5949
5950         switch(vid.renderpath)
5951         {
5952         case RENDERPATH_GL20:
5953         case RENDERPATH_D3D9:
5954         case RENDERPATH_D3D10:
5955         case RENDERPATH_D3D11:
5956         case RENDERPATH_SOFT:
5957         case RENDERPATH_GLES2:
5958                 break;
5959         case RENDERPATH_GL11:
5960         case RENDERPATH_GL13:
5961         case RENDERPATH_GLES1:
5962                 return;
5963         }
5964
5965         // set waterwidth and waterheight to the water resolution that will be
5966         // used (often less than the screen resolution for faster rendering)
5967         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5968
5969         // calculate desired texture sizes
5970         // can't use water if the card does not support the texture size
5971         if (!r_water.integer || r_showsurfaces.integer)
5972                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5973         else if (vid.support.arb_texture_non_power_of_two)
5974         {
5975                 texturewidth = waterwidth;
5976                 textureheight = waterheight;
5977                 camerawidth = waterwidth;
5978                 cameraheight = waterheight;
5979         }
5980         else
5981         {
5982                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5983                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5984                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5985                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5986         }
5987
5988         // allocate textures as needed
5989         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))
5990         {
5991                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5992                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5993                 {
5994                         if (p->texture_refraction)
5995                                 R_FreeTexture(p->texture_refraction);
5996                         p->texture_refraction = NULL;
5997                         if (p->fbo_refraction)
5998                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5999                         p->fbo_refraction = 0;
6000                         if (p->texture_reflection)
6001                                 R_FreeTexture(p->texture_reflection);
6002                         p->texture_reflection = NULL;
6003                         if (p->fbo_reflection)
6004                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6005                         p->fbo_reflection = 0;
6006                         if (p->texture_camera)
6007                                 R_FreeTexture(p->texture_camera);
6008                         p->texture_camera = NULL;
6009                         if (p->fbo_camera)
6010                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6011                         p->fbo_camera = 0;
6012                 }
6013                 memset(&r_fb.water, 0, sizeof(r_fb.water));
6014                 r_fb.water.texturewidth = texturewidth;
6015                 r_fb.water.textureheight = textureheight;
6016                 r_fb.water.camerawidth = camerawidth;
6017                 r_fb.water.cameraheight = cameraheight;
6018         }
6019
6020         if (r_fb.water.texturewidth)
6021         {
6022                 int scaledwidth, scaledheight;
6023
6024                 r_fb.water.enabled = true;
6025
6026                 // water resolution is usually reduced
6027                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6028                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6029                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6030
6031                 // set up variables that will be used in shader setup
6032                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6033                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6034                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6035                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6036         }
6037
6038         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6039         r_fb.water.numwaterplanes = 0;
6040 }
6041
6042 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6043 {
6044         int planeindex, bestplaneindex, vertexindex;
6045         vec3_t mins, maxs, normal, center, v, n;
6046         vec_t planescore, bestplanescore;
6047         mplane_t plane;
6048         r_waterstate_waterplane_t *p;
6049         texture_t *t = R_GetCurrentTexture(surface->texture);
6050
6051         rsurface.texture = t;
6052         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6053         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6054         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6055                 return;
6056         // average the vertex normals, find the surface bounds (after deformvertexes)
6057         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6058         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6059         VectorCopy(n, normal);
6060         VectorCopy(v, mins);
6061         VectorCopy(v, maxs);
6062         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6063         {
6064                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6065                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6066                 VectorAdd(normal, n, normal);
6067                 mins[0] = min(mins[0], v[0]);
6068                 mins[1] = min(mins[1], v[1]);
6069                 mins[2] = min(mins[2], v[2]);
6070                 maxs[0] = max(maxs[0], v[0]);
6071                 maxs[1] = max(maxs[1], v[1]);
6072                 maxs[2] = max(maxs[2], v[2]);
6073         }
6074         VectorNormalize(normal);
6075         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6076
6077         VectorCopy(normal, plane.normal);
6078         VectorNormalize(plane.normal);
6079         plane.dist = DotProduct(center, plane.normal);
6080         PlaneClassify(&plane);
6081         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6082         {
6083                 // skip backfaces (except if nocullface is set)
6084 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6085 //                      return;
6086                 VectorNegate(plane.normal, plane.normal);
6087                 plane.dist *= -1;
6088                 PlaneClassify(&plane);
6089         }
6090
6091
6092         // find a matching plane if there is one
6093         bestplaneindex = -1;
6094         bestplanescore = 1048576.0f;
6095         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6096         {
6097                 if(p->camera_entity == t->camera_entity)
6098                 {
6099                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6100                         if (bestplaneindex < 0 || bestplanescore > planescore)
6101                         {
6102                                 bestplaneindex = planeindex;
6103                                 bestplanescore = planescore;
6104                         }
6105                 }
6106         }
6107         planeindex = bestplaneindex;
6108
6109         // if this surface does not fit any known plane rendered this frame, add one
6110         if (planeindex < 0 || bestplanescore > 0.001f)
6111         {
6112                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6113                 {
6114                         // store the new plane
6115                         planeindex = r_fb.water.numwaterplanes++;
6116                         p = r_fb.water.waterplanes + planeindex;
6117                         p->plane = plane;
6118                         // clear materialflags and pvs
6119                         p->materialflags = 0;
6120                         p->pvsvalid = false;
6121                         p->camera_entity = t->camera_entity;
6122                         VectorCopy(mins, p->mins);
6123                         VectorCopy(maxs, p->maxs);
6124                 }
6125                 else
6126                 {
6127                         // We're totally screwed.
6128                         return;
6129                 }
6130         }
6131         else
6132         {
6133                 // merge mins/maxs when we're adding this surface to the plane
6134                 p = r_fb.water.waterplanes + planeindex;
6135                 p->mins[0] = min(p->mins[0], mins[0]);
6136                 p->mins[1] = min(p->mins[1], mins[1]);
6137                 p->mins[2] = min(p->mins[2], mins[2]);
6138                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6139                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6140                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6141         }
6142         // merge this surface's materialflags into the waterplane
6143         p->materialflags |= t->currentmaterialflags;
6144         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6145         {
6146                 // merge this surface's PVS into the waterplane
6147                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6148                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6149                 {
6150                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6151                         p->pvsvalid = true;
6152                 }
6153         }
6154 }
6155
6156 extern cvar_t r_drawparticles;
6157 extern cvar_t r_drawdecals;
6158
6159 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6160 {
6161         int myscissor[4];
6162         r_refdef_view_t originalview;
6163         r_refdef_view_t myview;
6164         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;
6165         r_waterstate_waterplane_t *p;
6166         vec3_t visorigin;
6167         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;
6168         char vabuf[1024];
6169
6170         originalview = r_refdef.view;
6171
6172         // lowquality hack, temporarily shut down some cvars and restore afterwards
6173         qualityreduction = r_water_lowquality.integer;
6174         if (qualityreduction > 0)
6175         {
6176                 if (qualityreduction >= 1)
6177                 {
6178                         old_r_shadows = r_shadows.integer;
6179                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6180                         old_r_dlight = r_shadow_realtime_dlight.integer;
6181                         Cvar_SetValueQuick(&r_shadows, 0);
6182                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6183                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6184                 }
6185                 if (qualityreduction >= 2)
6186                 {
6187                         old_r_dynamic = r_dynamic.integer;
6188                         old_r_particles = r_drawparticles.integer;
6189                         old_r_decals = r_drawdecals.integer;
6190                         Cvar_SetValueQuick(&r_dynamic, 0);
6191                         Cvar_SetValueQuick(&r_drawparticles, 0);
6192                         Cvar_SetValueQuick(&r_drawdecals, 0);
6193                 }
6194         }
6195
6196         // make sure enough textures are allocated
6197         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6198         {
6199                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6200                         continue;
6201                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6202                 {
6203                         if (!p->texture_refraction)
6204                                 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);
6205                         if (!p->texture_refraction)
6206                                 goto error;
6207                         if (usewaterfbo)
6208                         {
6209                                 if (r_fb.water.depthtexture == NULL)
6210                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6211                                 if (p->fbo_refraction == 0)
6212                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6213                         }
6214                 }
6215                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6216                 {
6217                         if (!p->texture_camera)
6218                                 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);
6219                         if (!p->texture_camera)
6220                                 goto error;
6221                         if (usewaterfbo)
6222                         {
6223                                 if (r_fb.water.depthtexture == NULL)
6224                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6225                                 if (p->fbo_camera == 0)
6226                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6227                         }
6228                 }
6229
6230                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6231                 {
6232                         if (!p->texture_reflection)
6233                                 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);
6234                         if (!p->texture_reflection)
6235                                 goto error;
6236                         if (usewaterfbo)
6237                         {
6238                                 if (r_fb.water.depthtexture == NULL)
6239                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6240                                 if (p->fbo_reflection == 0)
6241                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6242                         }
6243                 }
6244         }
6245
6246         // render views
6247         r_refdef.view = originalview;
6248         r_refdef.view.showdebug = false;
6249         r_refdef.view.width = r_fb.water.waterwidth;
6250         r_refdef.view.height = r_fb.water.waterheight;
6251         r_refdef.view.useclipplane = true;
6252         myview = r_refdef.view;
6253         r_fb.water.renderingscene = true;
6254         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6255         {
6256                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6257                         continue;
6258                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6259                 {
6260                         r_refdef.view = myview;
6261                         if(r_water_scissormode.integer)
6262                         {
6263                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6264                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6265                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6266                         }
6267
6268                         // render reflected scene and copy into texture
6269                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6270                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6271                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6272                         r_refdef.view.clipplane = p->plane;
6273                         // reverse the cullface settings for this render
6274                         r_refdef.view.cullface_front = GL_FRONT;
6275                         r_refdef.view.cullface_back = GL_BACK;
6276                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6277                         {
6278                                 r_refdef.view.usecustompvs = true;
6279                                 if (p->pvsvalid)
6280                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6281                                 else
6282                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6283                         }
6284
6285                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6286                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6287                         R_ClearScreen(r_refdef.fogenabled);
6288                         if(r_water_scissormode.integer & 2)
6289                                 R_View_UpdateWithScissor(myscissor);
6290                         else
6291                                 R_View_Update();
6292                         R_AnimCache_CacheVisibleEntities();
6293                         if(r_water_scissormode.integer & 1)
6294                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6295                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6296
6297                         if (!p->fbo_reflection)
6298                                 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);
6299                         r_fb.water.hideplayer = false;
6300                 }
6301
6302                 // render the normal view scene and copy into texture
6303                 // (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)
6304                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6305                 {
6306                         r_refdef.view = myview;
6307                         if(r_water_scissormode.integer)
6308                         {
6309                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6310                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6311                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6312                         }
6313
6314                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6315
6316                         r_refdef.view.clipplane = p->plane;
6317                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6318                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6319
6320                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6321                         {
6322                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6323                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6324                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6325                                 R_RenderView_UpdateViewVectors();
6326                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6327                                 {
6328                                         r_refdef.view.usecustompvs = true;
6329                                         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);
6330                                 }
6331                         }
6332
6333                         PlaneClassify(&r_refdef.view.clipplane);
6334
6335                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6336                         R_ClearScreen(r_refdef.fogenabled);
6337                         if(r_water_scissormode.integer & 2)
6338                                 R_View_UpdateWithScissor(myscissor);
6339                         else
6340                                 R_View_Update();
6341                         R_AnimCache_CacheVisibleEntities();
6342                         if(r_water_scissormode.integer & 1)
6343                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6344                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6345
6346                         if (!p->fbo_refraction)
6347                                 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);
6348                         r_fb.water.hideplayer = false;
6349                 }
6350                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6351                 {
6352                         r_refdef.view = myview;
6353
6354                         r_refdef.view.clipplane = p->plane;
6355                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6356                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6357
6358                         r_refdef.view.width = r_fb.water.camerawidth;
6359                         r_refdef.view.height = r_fb.water.cameraheight;
6360                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6361                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6362                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6363                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6364
6365                         if(p->camera_entity)
6366                         {
6367                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6368                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6369                         }
6370
6371                         // note: all of the view is used for displaying... so
6372                         // there is no use in scissoring
6373
6374                         // reverse the cullface settings for this render
6375                         r_refdef.view.cullface_front = GL_FRONT;
6376                         r_refdef.view.cullface_back = GL_BACK;
6377                         // also reverse the view matrix
6378                         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
6379                         R_RenderView_UpdateViewVectors();
6380                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6381                         {
6382                                 r_refdef.view.usecustompvs = true;
6383                                 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);
6384                         }
6385                         
6386                         // camera needs no clipplane
6387                         r_refdef.view.useclipplane = false;
6388
6389                         PlaneClassify(&r_refdef.view.clipplane);
6390
6391                         r_fb.water.hideplayer = false;
6392
6393                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6394                         R_ClearScreen(r_refdef.fogenabled);
6395                         R_View_Update();
6396                         R_AnimCache_CacheVisibleEntities();
6397                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6398
6399                         if (!p->fbo_camera)
6400                                 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);
6401                         r_fb.water.hideplayer = false;
6402                 }
6403
6404         }
6405         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6406         r_fb.water.renderingscene = false;
6407         r_refdef.view = originalview;
6408         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6409         if (!r_fb.water.depthtexture)
6410                 R_ClearScreen(r_refdef.fogenabled);
6411         R_View_Update();
6412         R_AnimCache_CacheVisibleEntities();
6413         goto finish;
6414 error:
6415         r_refdef.view = originalview;
6416         r_fb.water.renderingscene = false;
6417         Cvar_SetValueQuick(&r_water, 0);
6418         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6419 finish:
6420         // lowquality hack, restore cvars
6421         if (qualityreduction > 0)
6422         {
6423                 if (qualityreduction >= 1)
6424                 {
6425                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6426                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6427                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6428                 }
6429                 if (qualityreduction >= 2)
6430                 {
6431                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6432                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6433                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6434                 }
6435         }
6436 }
6437
6438 static void R_Bloom_StartFrame(void)
6439 {
6440         int i;
6441         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6442         int viewwidth, viewheight;
6443         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6444         textype_t textype = TEXTYPE_COLORBUFFER;
6445
6446         switch (vid.renderpath)
6447         {
6448         case RENDERPATH_GL20:
6449                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6450                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6451                 {
6452                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6453                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6454                 }
6455                 break;
6456         case RENDERPATH_GL11:
6457         case RENDERPATH_GL13:
6458         case RENDERPATH_GLES1:
6459         case RENDERPATH_GLES2:
6460         case RENDERPATH_D3D9:
6461         case RENDERPATH_D3D10:
6462         case RENDERPATH_D3D11:
6463                 r_fb.usedepthtextures = false;
6464                 break;
6465         case RENDERPATH_SOFT:
6466                 r_fb.usedepthtextures = true;
6467                 break;
6468         }
6469
6470         if (r_viewscale_fpsscaling.integer)
6471         {
6472                 double actualframetime;
6473                 double targetframetime;
6474                 double adjust;
6475                 actualframetime = r_refdef.lastdrawscreentime;
6476                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6477                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6478                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6479                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6480                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6481                 viewscalefpsadjusted += adjust;
6482                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6483         }
6484         else
6485                 viewscalefpsadjusted = 1.0f;
6486
6487         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6488
6489         switch(vid.renderpath)
6490         {
6491         case RENDERPATH_GL20:
6492         case RENDERPATH_D3D9:
6493         case RENDERPATH_D3D10:
6494         case RENDERPATH_D3D11:
6495         case RENDERPATH_SOFT:
6496         case RENDERPATH_GLES2:
6497                 break;
6498         case RENDERPATH_GL11:
6499         case RENDERPATH_GL13:
6500         case RENDERPATH_GLES1:
6501                 return;
6502         }
6503
6504         // set bloomwidth and bloomheight to the bloom resolution that will be
6505         // used (often less than the screen resolution for faster rendering)
6506         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6507         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6508         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6509         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6510         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6511
6512         // calculate desired texture sizes
6513         if (vid.support.arb_texture_non_power_of_two)
6514         {
6515                 screentexturewidth = vid.width;
6516                 screentextureheight = vid.height;
6517                 bloomtexturewidth = r_fb.bloomwidth;
6518                 bloomtextureheight = r_fb.bloomheight;
6519         }
6520         else
6521         {
6522                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6523                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6524                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6525                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6526         }
6527
6528         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))
6529         {
6530                 Cvar_SetValueQuick(&r_bloom, 0);
6531                 Cvar_SetValueQuick(&r_motionblur, 0);
6532                 Cvar_SetValueQuick(&r_damageblur, 0);
6533         }
6534
6535         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6536          && !r_bloom.integer
6537          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6538          && !useviewfbo
6539          && r_viewscale.value == 1.0f
6540          && !r_viewscale_fpsscaling.integer)
6541                 screentexturewidth = screentextureheight = 0;
6542         if (!r_bloom.integer)
6543                 bloomtexturewidth = bloomtextureheight = 0;
6544
6545         // allocate textures as needed
6546         if (r_fb.screentexturewidth != screentexturewidth
6547          || r_fb.screentextureheight != screentextureheight
6548          || r_fb.bloomtexturewidth != bloomtexturewidth
6549          || r_fb.bloomtextureheight != bloomtextureheight
6550          || r_fb.textype != textype
6551          || useviewfbo != (r_fb.fbo != 0))
6552         {
6553                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6554                 {
6555                         if (r_fb.bloomtexture[i])
6556                                 R_FreeTexture(r_fb.bloomtexture[i]);
6557                         r_fb.bloomtexture[i] = NULL;
6558
6559                         if (r_fb.bloomfbo[i])
6560                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6561                         r_fb.bloomfbo[i] = 0;
6562                 }
6563
6564                 if (r_fb.fbo)
6565                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6566                 r_fb.fbo = 0;
6567
6568                 if (r_fb.colortexture)
6569                         R_FreeTexture(r_fb.colortexture);
6570                 r_fb.colortexture = NULL;
6571
6572                 if (r_fb.depthtexture)
6573                         R_FreeTexture(r_fb.depthtexture);
6574                 r_fb.depthtexture = NULL;
6575
6576                 if (r_fb.ghosttexture)
6577                         R_FreeTexture(r_fb.ghosttexture);
6578                 r_fb.ghosttexture = NULL;
6579
6580                 r_fb.screentexturewidth = screentexturewidth;
6581                 r_fb.screentextureheight = screentextureheight;
6582                 r_fb.bloomtexturewidth = bloomtexturewidth;
6583                 r_fb.bloomtextureheight = bloomtextureheight;
6584                 r_fb.textype = textype;
6585
6586                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6587                 {
6588                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6589                                 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);
6590                         r_fb.ghosttexture_valid = false;
6591                         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);
6592                         if (useviewfbo)
6593                         {
6594                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6595                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6596                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6597                         }
6598                 }
6599
6600                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6601                 {
6602                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6603                         {
6604                                 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);
6605                                 if (useviewfbo)
6606                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6607                         }
6608                 }
6609         }
6610
6611         // bloom texture is a different resolution
6612         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6613         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6614         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6615         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6616         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6617
6618         // set up a texcoord array for the full resolution screen image
6619         // (we have to keep this around to copy back during final render)
6620         r_fb.screentexcoord2f[0] = 0;
6621         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6622         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6623         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6624         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6625         r_fb.screentexcoord2f[5] = 0;
6626         r_fb.screentexcoord2f[6] = 0;
6627         r_fb.screentexcoord2f[7] = 0;
6628
6629         if(r_fb.fbo) 
6630         {
6631                 for (i = 1;i < 8;i += 2)
6632                 {
6633                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6634                 }
6635         }
6636
6637         // set up a texcoord array for the reduced resolution bloom image
6638         // (which will be additive blended over the screen image)
6639         r_fb.bloomtexcoord2f[0] = 0;
6640         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6641         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6642         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6643         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6644         r_fb.bloomtexcoord2f[5] = 0;
6645         r_fb.bloomtexcoord2f[6] = 0;
6646         r_fb.bloomtexcoord2f[7] = 0;
6647
6648         switch(vid.renderpath)
6649         {
6650         case RENDERPATH_GL11:
6651         case RENDERPATH_GL13:
6652         case RENDERPATH_GL20:
6653         case RENDERPATH_SOFT:
6654         case RENDERPATH_GLES1:
6655         case RENDERPATH_GLES2:
6656                 break;
6657         case RENDERPATH_D3D9:
6658         case RENDERPATH_D3D10:
6659         case RENDERPATH_D3D11:
6660                 for (i = 0;i < 4;i++)
6661                 {
6662                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6663                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6664                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6665                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6666                 }
6667                 break;
6668         }
6669
6670         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6671
6672         if (r_fb.fbo)
6673                 r_refdef.view.clear = true;
6674 }
6675
6676 static void R_Bloom_MakeTexture(void)
6677 {
6678         int x, range, dir;
6679         float xoffset, yoffset, r, brighten;
6680         rtexture_t *intex;
6681         float colorscale = r_bloom_colorscale.value;
6682
6683         r_refdef.stats[r_stat_bloom]++;
6684     
6685 #if 0
6686     // this copy is unnecessary since it happens in R_BlendView already
6687         if (!r_fb.fbo)
6688         {
6689                 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);
6690                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6691         }
6692 #endif
6693
6694         // scale down screen texture to the bloom texture size
6695         CHECKGLERROR
6696         r_fb.bloomindex = 0;
6697         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6698         R_SetViewport(&r_fb.bloomviewport);
6699         GL_CullFace(GL_NONE);
6700         GL_DepthTest(false);
6701         GL_BlendFunc(GL_ONE, GL_ZERO);
6702         GL_Color(colorscale, colorscale, colorscale, 1);
6703         // 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...
6704         switch(vid.renderpath)
6705         {
6706         case RENDERPATH_GL11:
6707         case RENDERPATH_GL13:
6708         case RENDERPATH_GL20:
6709         case RENDERPATH_GLES1:
6710         case RENDERPATH_GLES2:
6711         case RENDERPATH_SOFT:
6712                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6713                 break;
6714         case RENDERPATH_D3D9:
6715         case RENDERPATH_D3D10:
6716         case RENDERPATH_D3D11:
6717                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6718                 break;
6719         }
6720         // TODO: do boxfilter scale-down in shader?
6721         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6722         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6723         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6724
6725         // we now have a properly scaled bloom image
6726         if (!r_fb.bloomfbo[r_fb.bloomindex])
6727         {
6728                 // copy it into the bloom texture
6729                 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);
6730                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6731         }
6732
6733         // multiply bloom image by itself as many times as desired
6734         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6735         {
6736                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6737                 r_fb.bloomindex ^= 1;
6738                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6739                 x *= 2;
6740                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6741                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6742                 {
6743                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6744                         GL_Color(r,r,r,1); // apply fix factor
6745                 }
6746                 else
6747                 {
6748                         if(x <= 2)
6749                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6750                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6751                         GL_Color(1,1,1,1); // no fix factor supported here
6752                 }
6753                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6754                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6755                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6756                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6757
6758                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6759                 {
6760                         // copy the darkened image to a texture
6761                         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);
6762                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6763                 }
6764         }
6765
6766         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6767         brighten = r_bloom_brighten.value;
6768         brighten = sqrt(brighten);
6769         if(range >= 1)
6770                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6771
6772         for (dir = 0;dir < 2;dir++)
6773         {
6774                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6775                 r_fb.bloomindex ^= 1;
6776                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6777                 // blend on at multiple vertical offsets to achieve a vertical blur
6778                 // TODO: do offset blends using GLSL
6779                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6780                 GL_BlendFunc(GL_ONE, GL_ZERO);
6781                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6782                 for (x = -range;x <= range;x++)
6783                 {
6784                         if (!dir){xoffset = 0;yoffset = x;}
6785                         else {xoffset = x;yoffset = 0;}
6786                         xoffset /= (float)r_fb.bloomtexturewidth;
6787                         yoffset /= (float)r_fb.bloomtextureheight;
6788                         // compute a texcoord array with the specified x and y offset
6789                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6790                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6791                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6792                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6793                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6794                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6795                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6796                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6797                         // this r value looks like a 'dot' particle, fading sharply to
6798                         // black at the edges
6799                         // (probably not realistic but looks good enough)
6800                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6801                         //r = brighten/(range*2+1);
6802                         r = brighten / (range * 2 + 1);
6803                         if(range >= 1)
6804                                 r *= (1 - x*x/(float)(range*range));
6805                         GL_Color(r, r, r, 1);
6806                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6807                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6808                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6809                         GL_BlendFunc(GL_ONE, GL_ONE);
6810                 }
6811
6812                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6813                 {
6814                         // copy the vertically or horizontally blurred bloom view to a texture
6815                         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);
6816                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6817                 }
6818         }
6819 }
6820
6821 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6822 {
6823         unsigned int permutation;
6824         float uservecs[4][4];
6825
6826         R_EntityMatrix(&identitymatrix);
6827
6828         switch (vid.renderpath)
6829         {
6830         case RENDERPATH_GL20:
6831         case RENDERPATH_D3D9:
6832         case RENDERPATH_D3D10:
6833         case RENDERPATH_D3D11:
6834         case RENDERPATH_SOFT:
6835         case RENDERPATH_GLES2:
6836                 permutation =
6837                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6838                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6839                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6840                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6841                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6842
6843                 if (r_fb.colortexture)
6844                 {
6845                         if (!r_fb.fbo)
6846                         {
6847                                 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);
6848                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6849                         }
6850
6851                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6852                         {
6853                                 // declare variables
6854                                 float blur_factor, blur_mouseaccel, blur_velocity;
6855                                 static float blur_average; 
6856                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6857
6858                                 // set a goal for the factoring
6859                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6860                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6861                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6862                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6863                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6864                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6865
6866                                 // from the goal, pick an averaged value between goal and last value
6867                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6868                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6869
6870                                 // enforce minimum amount of blur 
6871                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6872
6873                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6874
6875                                 // calculate values into a standard alpha
6876                                 cl.motionbluralpha = 1 - exp(-
6877                                                 (
6878                                                  (r_motionblur.value * blur_factor / 80)
6879                                                  +
6880                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6881                                                 )
6882                                                 /
6883                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6884                                           );
6885
6886                                 // randomization for the blur value to combat persistent ghosting
6887                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6888                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6889
6890                                 // apply the blur
6891                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6892                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6893                                 {
6894                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6895                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6896                                         switch(vid.renderpath)
6897                                         {
6898                                         case RENDERPATH_GL11:
6899                                         case RENDERPATH_GL13:
6900                                         case RENDERPATH_GL20:
6901                                         case RENDERPATH_GLES1:
6902                                         case RENDERPATH_GLES2:
6903                                         case RENDERPATH_SOFT:
6904                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6905                                                 break;
6906                                         case RENDERPATH_D3D9:
6907                                         case RENDERPATH_D3D10:
6908                                         case RENDERPATH_D3D11:
6909                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6910                                                 break;
6911                                         }
6912                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6913                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6914                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6915                                 }
6916
6917                                 // updates old view angles for next pass
6918                                 VectorCopy(cl.viewangles, blur_oldangles);
6919
6920                                 // copy view into the ghost texture
6921                                 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);
6922                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6923                                 r_fb.ghosttexture_valid = true;
6924                         }
6925                 }
6926                 else
6927                 {
6928                         // no r_fb.colortexture means we're rendering to the real fb
6929                         // we may still have to do view tint...
6930                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6931                         {
6932                                 // apply a color tint to the whole view
6933                                 R_ResetViewRendering2D(0, NULL, NULL);
6934                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6935                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6936                                 R_SetupShader_Generic_NoTexture(false, true);
6937                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6938                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6939                         }
6940                         break; // no screen processing, no bloom, skip it
6941                 }
6942
6943                 if (r_fb.bloomtexture[0])
6944                 {
6945                         // make the bloom texture
6946                         R_Bloom_MakeTexture();
6947                 }
6948
6949 #if _MSC_VER >= 1400
6950 #define sscanf sscanf_s
6951 #endif
6952                 memset(uservecs, 0, sizeof(uservecs));
6953                 if (r_glsl_postprocess_uservec1_enable.integer)
6954                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6955                 if (r_glsl_postprocess_uservec2_enable.integer)
6956                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6957                 if (r_glsl_postprocess_uservec3_enable.integer)
6958                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6959                 if (r_glsl_postprocess_uservec4_enable.integer)
6960                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6961
6962                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6963                 GL_Color(1, 1, 1, 1);
6964                 GL_BlendFunc(GL_ONE, GL_ZERO);
6965
6966                 switch(vid.renderpath)
6967                 {
6968                 case RENDERPATH_GL20:
6969                 case RENDERPATH_GLES2:
6970                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6971                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6972                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6973                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6974                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6975                         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]);
6976                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6977                         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]);
6978                         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]);
6979                         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]);
6980                         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]);
6981                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6982                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6983                         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);
6984                         break;
6985                 case RENDERPATH_D3D9:
6986 #ifdef SUPPORTD3D
6987                         // 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...
6988                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6989                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6990                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6991                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6992                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6993                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6994                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6995                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6996                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6997                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6998                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6999                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
7000                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7001                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7002 #endif
7003                         break;
7004                 case RENDERPATH_D3D10:
7005                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7006                         break;
7007                 case RENDERPATH_D3D11:
7008                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7009                         break;
7010                 case RENDERPATH_SOFT:
7011                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7012                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7013                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
7014                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
7015                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7016                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7017                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7018                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7019                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7020                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7021                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7022                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
7023                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7024                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7025                         break;
7026                 default:
7027                         break;
7028                 }
7029                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7030                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7031                 break;
7032         case RENDERPATH_GL11:
7033         case RENDERPATH_GL13:
7034         case RENDERPATH_GLES1:
7035                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7036                 {
7037                         // apply a color tint to the whole view
7038                         R_ResetViewRendering2D(0, NULL, NULL);
7039                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7040                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7041                         R_SetupShader_Generic_NoTexture(false, true);
7042                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7043                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7044                 }
7045                 break;
7046         }
7047 }
7048
7049 matrix4x4_t r_waterscrollmatrix;
7050
7051 void R_UpdateFog(void)
7052 {
7053         // Nehahra fog
7054         if (gamemode == GAME_NEHAHRA)
7055         {
7056                 if (gl_fogenable.integer)
7057                 {
7058                         r_refdef.oldgl_fogenable = true;
7059                         r_refdef.fog_density = gl_fogdensity.value;
7060                         r_refdef.fog_red = gl_fogred.value;
7061                         r_refdef.fog_green = gl_foggreen.value;
7062                         r_refdef.fog_blue = gl_fogblue.value;
7063                         r_refdef.fog_alpha = 1;
7064                         r_refdef.fog_start = 0;
7065                         r_refdef.fog_end = gl_skyclip.value;
7066                         r_refdef.fog_height = 1<<30;
7067                         r_refdef.fog_fadedepth = 128;
7068                 }
7069                 else if (r_refdef.oldgl_fogenable)
7070                 {
7071                         r_refdef.oldgl_fogenable = false;
7072                         r_refdef.fog_density = 0;
7073                         r_refdef.fog_red = 0;
7074                         r_refdef.fog_green = 0;
7075                         r_refdef.fog_blue = 0;
7076                         r_refdef.fog_alpha = 0;
7077                         r_refdef.fog_start = 0;
7078                         r_refdef.fog_end = 0;
7079                         r_refdef.fog_height = 1<<30;
7080                         r_refdef.fog_fadedepth = 128;
7081                 }
7082         }
7083
7084         // fog parms
7085         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7086         r_refdef.fog_start = max(0, r_refdef.fog_start);
7087         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7088
7089         if (r_refdef.fog_density && r_drawfog.integer)
7090         {
7091                 r_refdef.fogenabled = true;
7092                 // this is the point where the fog reaches 0.9986 alpha, which we
7093                 // consider a good enough cutoff point for the texture
7094                 // (0.9986 * 256 == 255.6)
7095                 if (r_fog_exp2.integer)
7096                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7097                 else
7098                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7099                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7100                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7101                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7102                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7103                         R_BuildFogHeightTexture();
7104                 // fog color was already set
7105                 // update the fog texture
7106                 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)
7107                         R_BuildFogTexture();
7108                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7109                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7110         }
7111         else
7112                 r_refdef.fogenabled = false;
7113
7114         // fog color
7115         if (r_refdef.fog_density)
7116         {
7117                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7118                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7119                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7120
7121                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7122                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7123                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7124                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7125
7126                 {
7127                         vec3_t fogvec;
7128                         VectorCopy(r_refdef.fogcolor, fogvec);
7129                         //   color.rgb *= ContrastBoost * SceneBrightness;
7130                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7131                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7132                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7133                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7134                 }
7135         }
7136 }
7137
7138 void R_UpdateVariables(void)
7139 {
7140         R_Textures_Frame();
7141
7142         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7143
7144         r_refdef.farclip = r_farclip_base.value;
7145         if (r_refdef.scene.worldmodel)
7146                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7147         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7148
7149         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7150                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7151         r_refdef.polygonfactor = 0;
7152         r_refdef.polygonoffset = 0;
7153         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7154         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7155
7156         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7157         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7158         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7159         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7160         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7161         if (FAKELIGHT_ENABLED)
7162         {
7163                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7164         }
7165         else if (r_refdef.scene.worldmodel)
7166         {
7167                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7168         }
7169         if (r_showsurfaces.integer)
7170         {
7171                 r_refdef.scene.rtworld = false;
7172                 r_refdef.scene.rtworldshadows = false;
7173                 r_refdef.scene.rtdlight = false;
7174                 r_refdef.scene.rtdlightshadows = false;
7175                 r_refdef.lightmapintensity = 0;
7176         }
7177
7178         r_gpuskeletal = false;
7179         switch(vid.renderpath)
7180         {
7181         case RENDERPATH_GL20:
7182                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7183         case RENDERPATH_D3D9:
7184         case RENDERPATH_D3D10:
7185         case RENDERPATH_D3D11:
7186         case RENDERPATH_SOFT:
7187         case RENDERPATH_GLES2:
7188                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7189                 {
7190                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7191                         {
7192                                 // build GLSL gamma texture
7193 #define RAMPWIDTH 256
7194                                 unsigned short ramp[RAMPWIDTH * 3];
7195                                 unsigned char rampbgr[RAMPWIDTH][4];
7196                                 int i;
7197
7198                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7199
7200                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7201                                 for(i = 0; i < RAMPWIDTH; ++i)
7202                                 {
7203                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7204                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7205                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7206                                         rampbgr[i][3] = 0;
7207                                 }
7208                                 if (r_texture_gammaramps)
7209                                 {
7210                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7211                                 }
7212                                 else
7213                                 {
7214                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7215                                 }
7216                         }
7217                 }
7218                 else
7219                 {
7220                         // remove GLSL gamma texture
7221                 }
7222                 break;
7223         case RENDERPATH_GL11:
7224         case RENDERPATH_GL13:
7225         case RENDERPATH_GLES1:
7226                 break;
7227         }
7228 }
7229
7230 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7231 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7232 /*
7233 ================
7234 R_SelectScene
7235 ================
7236 */
7237 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7238         if( scenetype != r_currentscenetype ) {
7239                 // store the old scenetype
7240                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7241                 r_currentscenetype = scenetype;
7242                 // move in the new scene
7243                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7244         }
7245 }
7246
7247 /*
7248 ================
7249 R_GetScenePointer
7250 ================
7251 */
7252 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7253 {
7254         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7255         if( scenetype == r_currentscenetype ) {
7256                 return &r_refdef.scene;
7257         } else {
7258                 return &r_scenes_store[ scenetype ];
7259         }
7260 }
7261
7262 static int R_SortEntities_Compare(const void *ap, const void *bp)
7263 {
7264         const entity_render_t *a = *(const entity_render_t **)ap;
7265         const entity_render_t *b = *(const entity_render_t **)bp;
7266
7267         // 1. compare model
7268         if(a->model < b->model)
7269                 return -1;
7270         if(a->model > b->model)
7271                 return +1;
7272
7273         // 2. compare skin
7274         // TODO possibly calculate the REAL skinnum here first using
7275         // skinscenes?
7276         if(a->skinnum < b->skinnum)
7277                 return -1;
7278         if(a->skinnum > b->skinnum)
7279                 return +1;
7280
7281         // everything we compared is equal
7282         return 0;
7283 }
7284 static void R_SortEntities(void)
7285 {
7286         // below or equal 2 ents, sorting never gains anything
7287         if(r_refdef.scene.numentities <= 2)
7288                 return;
7289         // sort
7290         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7291 }
7292
7293 /*
7294 ================
7295 R_RenderView
7296 ================
7297 */
7298 int dpsoftrast_test;
7299 extern cvar_t r_shadow_bouncegrid;
7300 void R_RenderView(void)
7301 {
7302         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7303         int fbo;
7304         rtexture_t *depthtexture;
7305         rtexture_t *colortexture;
7306
7307         dpsoftrast_test = r_test.integer;
7308
7309         if (r_timereport_active)
7310                 R_TimeReport("start");
7311         r_textureframe++; // used only by R_GetCurrentTexture
7312         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7313
7314         if(R_CompileShader_CheckStaticParms())
7315                 R_GLSL_Restart_f();
7316
7317         if (!r_drawentities.integer)
7318                 r_refdef.scene.numentities = 0;
7319         else if (r_sortentities.integer)
7320                 R_SortEntities();
7321
7322         R_AnimCache_ClearCache();
7323
7324         /* adjust for stereo display */
7325         if(R_Stereo_Active())
7326         {
7327                 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);
7328                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7329         }
7330
7331         if (r_refdef.view.isoverlay)
7332         {
7333                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7334                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7335                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7336                 R_TimeReport("depthclear");
7337
7338                 r_refdef.view.showdebug = false;
7339
7340                 r_fb.water.enabled = false;
7341                 r_fb.water.numwaterplanes = 0;
7342
7343                 R_RenderScene(0, NULL, NULL);
7344
7345                 r_refdef.view.matrix = originalmatrix;
7346
7347                 CHECKGLERROR
7348                 return;
7349         }
7350
7351         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7352         {
7353                 r_refdef.view.matrix = originalmatrix;
7354                 return;
7355         }
7356
7357         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7358
7359         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7360                 // in sRGB fallback, behave similar to true sRGB: convert this
7361                 // value from linear to sRGB
7362                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7363
7364         R_RenderView_UpdateViewVectors();
7365
7366         R_Shadow_UpdateWorldLightSelection();
7367
7368         R_Bloom_StartFrame();
7369
7370         // apply bloom brightness offset
7371         if(r_fb.bloomtexture[0])
7372                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7373
7374         R_Water_StartFrame();
7375
7376         // now we probably have an fbo to render into
7377         fbo = r_fb.fbo;
7378         depthtexture = r_fb.depthtexture;
7379         colortexture = r_fb.colortexture;
7380
7381         CHECKGLERROR
7382         if (r_timereport_active)
7383                 R_TimeReport("viewsetup");
7384
7385         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7386
7387         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7388         {
7389                 R_ClearScreen(r_refdef.fogenabled);
7390                 if (r_timereport_active)
7391                         R_TimeReport("viewclear");
7392         }
7393         r_refdef.view.clear = true;
7394
7395         r_refdef.view.showdebug = true;
7396
7397         R_View_Update();
7398         if (r_timereport_active)
7399                 R_TimeReport("visibility");
7400
7401         R_AnimCache_CacheVisibleEntities();
7402         if (r_timereport_active)
7403                 R_TimeReport("animcache");
7404
7405         R_Shadow_UpdateBounceGridTexture();
7406         if (r_timereport_active && r_shadow_bouncegrid.integer)
7407                 R_TimeReport("bouncegrid");
7408
7409         r_fb.water.numwaterplanes = 0;
7410         if (r_fb.water.enabled)
7411                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7412
7413         R_RenderScene(fbo, depthtexture, colortexture);
7414         r_fb.water.numwaterplanes = 0;
7415
7416         R_BlendView(fbo, depthtexture, colortexture);
7417         if (r_timereport_active)
7418                 R_TimeReport("blendview");
7419
7420         GL_Scissor(0, 0, vid.width, vid.height);
7421         GL_ScissorTest(false);
7422
7423         r_refdef.view.matrix = originalmatrix;
7424
7425         CHECKGLERROR
7426 }
7427
7428 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7429 {
7430         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7431         {
7432                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7433                 if (r_timereport_active)
7434                         R_TimeReport("waterworld");
7435         }
7436
7437         // don't let sound skip if going slow
7438         if (r_refdef.scene.extraupdate)
7439                 S_ExtraUpdate ();
7440
7441         R_DrawModelsAddWaterPlanes();
7442         if (r_timereport_active)
7443                 R_TimeReport("watermodels");
7444
7445         if (r_fb.water.numwaterplanes)
7446         {
7447                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7448                 if (r_timereport_active)
7449                         R_TimeReport("waterscenes");
7450         }
7451 }
7452
7453 extern cvar_t cl_locs_show;
7454 static void R_DrawLocs(void);
7455 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7456 static void R_DrawModelDecals(void);
7457 extern cvar_t cl_decals_newsystem;
7458 extern qboolean r_shadow_usingdeferredprepass;
7459 extern int r_shadow_shadowmapatlas_modelshadows_size;
7460 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7461 {
7462         qboolean shadowmapping = false;
7463
7464         if (r_timereport_active)
7465                 R_TimeReport("beginscene");
7466
7467         r_refdef.stats[r_stat_renders]++;
7468
7469         R_UpdateFog();
7470
7471         // don't let sound skip if going slow
7472         if (r_refdef.scene.extraupdate)
7473                 S_ExtraUpdate ();
7474
7475         R_MeshQueue_BeginScene();
7476
7477         R_SkyStartFrame();
7478
7479         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);
7480
7481         if (r_timereport_active)
7482                 R_TimeReport("skystartframe");
7483
7484         if (cl.csqc_vidvars.drawworld)
7485         {
7486                 // don't let sound skip if going slow
7487                 if (r_refdef.scene.extraupdate)
7488                         S_ExtraUpdate ();
7489
7490                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7491                 {
7492                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7493                         if (r_timereport_active)
7494                                 R_TimeReport("worldsky");
7495                 }
7496
7497                 if (R_DrawBrushModelsSky() && r_timereport_active)
7498                         R_TimeReport("bmodelsky");
7499
7500                 if (skyrendermasked && skyrenderlater)
7501                 {
7502                         // we have to force off the water clipping plane while rendering sky
7503                         R_SetupView(false, fbo, depthtexture, colortexture);
7504                         R_Sky();
7505                         R_SetupView(true, fbo, depthtexture, colortexture);
7506                         if (r_timereport_active)
7507                                 R_TimeReport("sky");
7508                 }
7509         }
7510
7511         R_Shadow_PrepareModelShadows();
7512         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7513         if (r_timereport_active)
7514                 R_TimeReport("preparelights");
7515
7516         // render all the shadowmaps that will be used for this view
7517         shadowmapping = R_Shadow_ShadowMappingEnabled();
7518         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7519         {
7520                 R_Shadow_DrawShadowMaps();
7521                 if (r_timereport_active)
7522                         R_TimeReport("shadowmaps");
7523         }
7524
7525         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7526         if (r_shadow_usingdeferredprepass)
7527                 R_Shadow_DrawPrepass();
7528
7529         // now we begin the forward pass of the view render
7530         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7531         {
7532                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7533                 if (r_timereport_active)
7534                         R_TimeReport("worlddepth");
7535         }
7536         if (r_depthfirst.integer >= 2)
7537         {
7538                 R_DrawModelsDepth();
7539                 if (r_timereport_active)
7540                         R_TimeReport("modeldepth");
7541         }
7542
7543         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7544         {
7545                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7546                 if (r_timereport_active)
7547                         R_TimeReport("world");
7548         }
7549
7550         // don't let sound skip if going slow
7551         if (r_refdef.scene.extraupdate)
7552                 S_ExtraUpdate ();
7553
7554         R_DrawModels();
7555         if (r_timereport_active)
7556                 R_TimeReport("models");
7557
7558         // don't let sound skip if going slow
7559         if (r_refdef.scene.extraupdate)
7560                 S_ExtraUpdate ();
7561
7562         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7563         {
7564                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7565                 R_Shadow_DrawModelShadows();
7566                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7567                 // don't let sound skip if going slow
7568                 if (r_refdef.scene.extraupdate)
7569                         S_ExtraUpdate ();
7570         }
7571
7572         if (!r_shadow_usingdeferredprepass)
7573         {
7574                 R_Shadow_DrawLights();
7575                 if (r_timereport_active)
7576                         R_TimeReport("rtlights");
7577         }
7578
7579         // don't let sound skip if going slow
7580         if (r_refdef.scene.extraupdate)
7581                 S_ExtraUpdate ();
7582
7583         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7584         {
7585                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7586                 R_Shadow_DrawModelShadows();
7587                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7588                 // don't let sound skip if going slow
7589                 if (r_refdef.scene.extraupdate)
7590                         S_ExtraUpdate ();
7591         }
7592
7593         if (cl.csqc_vidvars.drawworld)
7594         {
7595                 if (cl_decals_newsystem.integer)
7596                 {
7597                         R_DrawModelDecals();
7598                         if (r_timereport_active)
7599                                 R_TimeReport("modeldecals");
7600                 }
7601                 else
7602                 {
7603                         R_DrawDecals();
7604                         if (r_timereport_active)
7605                                 R_TimeReport("decals");
7606                 }
7607
7608                 R_DrawParticles();
7609                 if (r_timereport_active)
7610                         R_TimeReport("particles");
7611
7612                 R_DrawExplosions();
7613                 if (r_timereport_active)
7614                         R_TimeReport("explosions");
7615
7616                 R_DrawLightningBeams();
7617                 if (r_timereport_active)
7618                         R_TimeReport("lightning");
7619         }
7620
7621         if (cl.csqc_loaded)
7622                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7623
7624         if (r_refdef.view.showdebug)
7625         {
7626                 if (cl_locs_show.integer)
7627                 {
7628                         R_DrawLocs();
7629                         if (r_timereport_active)
7630                                 R_TimeReport("showlocs");
7631                 }
7632
7633                 if (r_drawportals.integer)
7634                 {
7635                         R_DrawPortals();
7636                         if (r_timereport_active)
7637                                 R_TimeReport("portals");
7638                 }
7639
7640                 if (r_showbboxes_client.value > 0)
7641                 {
7642                         R_DrawEntityBBoxes(CLVM_prog);
7643                         if (r_timereport_active)
7644                                 R_TimeReport("clbboxes");
7645                 }
7646                 if (r_showbboxes.value > 0)
7647                 {
7648                         R_DrawEntityBBoxes(SVVM_prog);
7649                         if (r_timereport_active)
7650                                 R_TimeReport("svbboxes");
7651                 }
7652         }
7653
7654         if (r_transparent.integer)
7655         {
7656                 R_MeshQueue_RenderTransparent();
7657                 if (r_timereport_active)
7658                         R_TimeReport("drawtrans");
7659         }
7660
7661         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))
7662         {
7663                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7664                 if (r_timereport_active)
7665                         R_TimeReport("worlddebug");
7666                 R_DrawModelsDebug();
7667                 if (r_timereport_active)
7668                         R_TimeReport("modeldebug");
7669         }
7670
7671         if (cl.csqc_vidvars.drawworld)
7672         {
7673                 R_Shadow_DrawCoronas();
7674                 if (r_timereport_active)
7675                         R_TimeReport("coronas");
7676         }
7677
7678 #if 0
7679         {
7680                 GL_DepthTest(false);
7681                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7682                 GL_Color(1, 1, 1, 1);
7683                 qglBegin(GL_POLYGON);
7684                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7685                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7686                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7687                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7688                 qglEnd();
7689                 qglBegin(GL_POLYGON);
7690                 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]);
7691                 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]);
7692                 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]);
7693                 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]);
7694                 qglEnd();
7695                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7696         }
7697 #endif
7698
7699         // don't let sound skip if going slow
7700         if (r_refdef.scene.extraupdate)
7701                 S_ExtraUpdate ();
7702 }
7703
7704 static const unsigned short bboxelements[36] =
7705 {
7706         5, 1, 3, 5, 3, 7,
7707         6, 2, 0, 6, 0, 4,
7708         7, 3, 2, 7, 2, 6,
7709         4, 0, 1, 4, 1, 5,
7710         4, 5, 7, 4, 7, 6,
7711         1, 0, 2, 1, 2, 3,
7712 };
7713
7714 #define BBOXEDGES 13
7715 static const float bboxedges[BBOXEDGES][6] = 
7716 {
7717         // whole box
7718         { 0, 0, 0, 1, 1, 1 },
7719         // bottom edges
7720         { 0, 0, 0, 0, 1, 0 },
7721         { 0, 0, 0, 1, 0, 0 },
7722         { 0, 1, 0, 1, 1, 0 },
7723         { 1, 0, 0, 1, 1, 0 },
7724         // top edges
7725         { 0, 0, 1, 0, 1, 1 },
7726         { 0, 0, 1, 1, 0, 1 },
7727         { 0, 1, 1, 1, 1, 1 },
7728         { 1, 0, 1, 1, 1, 1 },
7729         // vertical edges
7730         { 0, 0, 0, 0, 0, 1 },
7731         { 1, 0, 0, 1, 0, 1 },
7732         { 0, 1, 0, 0, 1, 1 },
7733         { 1, 1, 0, 1, 1, 1 },
7734 };
7735
7736 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7737 {
7738         int numvertices = BBOXEDGES * 8;
7739         float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7740         int numtriangles = BBOXEDGES * 12;
7741         unsigned short elements[BBOXEDGES * 36];
7742         int i, edge;
7743         float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7744
7745         RSurf_ActiveWorldEntity();
7746
7747         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7748         GL_DepthMask(false);
7749         GL_DepthRange(0, 1);
7750         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7751
7752         for (edge = 0; edge < BBOXEDGES; edge++)
7753         {
7754                 for (i = 0; i < 3; i++)
7755                 {
7756                         edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7757                         edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7758                 }
7759                 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7760                 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7761                 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7762                 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7763                 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7764                 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7765                 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7766                 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7767                 for (i = 0; i < 36; i++)
7768                         elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7769         }
7770         R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7771         if (r_refdef.fogenabled)
7772         {
7773                 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7774                 {
7775                         f1 = RSurf_FogVertex(v);
7776                         f2 = 1 - f1;
7777                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7778                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7779                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7780                 }
7781         }
7782         R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7783         R_Mesh_ResetTextureState();
7784         R_SetupShader_Generic_NoTexture(false, false);
7785         R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7786 }
7787
7788 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7789 {
7790         // hacky overloading of the parameters
7791         prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7792         int i;
7793         float color[4];
7794         prvm_edict_t *edict;
7795
7796         GL_CullFace(GL_NONE);
7797         R_SetupShader_Generic_NoTexture(false, false);
7798
7799         for (i = 0;i < numsurfaces;i++)
7800         {
7801                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7802                 switch ((int)PRVM_serveredictfloat(edict, solid))
7803                 {
7804                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7805                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7806                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7807                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7808                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7809                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7810                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7811                 }
7812                 if (prog == CLVM_prog)
7813                         color[3] *= r_showbboxes_client.value;
7814                 else
7815                         color[3] *= r_showbboxes.value;
7816                 color[3] = bound(0, color[3], 1);
7817                 GL_DepthTest(!r_showdisabledepthtest.integer);
7818                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7819         }
7820 }
7821
7822 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7823 {
7824         int i;
7825         prvm_edict_t *edict;
7826         vec3_t center;
7827
7828         if (prog == NULL)
7829                 return;
7830
7831         for (i = 0; i < prog->num_edicts; i++)
7832         {
7833                 edict = PRVM_EDICT_NUM(i);
7834                 if (edict->priv.server->free)
7835                         continue;
7836                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7837                 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7838                         continue;
7839                 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7840                         continue;
7841                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7842                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7843         }
7844 }
7845
7846 static const int nomodelelement3i[24] =
7847 {
7848         5, 2, 0,
7849         5, 1, 2,
7850         5, 0, 3,
7851         5, 3, 1,
7852         0, 2, 4,
7853         2, 1, 4,
7854         3, 0, 4,
7855         1, 3, 4
7856 };
7857
7858 static const unsigned short nomodelelement3s[24] =
7859 {
7860         5, 2, 0,
7861         5, 1, 2,
7862         5, 0, 3,
7863         5, 3, 1,
7864         0, 2, 4,
7865         2, 1, 4,
7866         3, 0, 4,
7867         1, 3, 4
7868 };
7869
7870 static const float nomodelvertex3f[6*3] =
7871 {
7872         -16,   0,   0,
7873          16,   0,   0,
7874           0, -16,   0,
7875           0,  16,   0,
7876           0,   0, -16,
7877           0,   0,  16
7878 };
7879
7880 static const float nomodelcolor4f[6*4] =
7881 {
7882         0.0f, 0.0f, 0.5f, 1.0f,
7883         0.0f, 0.0f, 0.5f, 1.0f,
7884         0.0f, 0.5f, 0.0f, 1.0f,
7885         0.0f, 0.5f, 0.0f, 1.0f,
7886         0.5f, 0.0f, 0.0f, 1.0f,
7887         0.5f, 0.0f, 0.0f, 1.0f
7888 };
7889
7890 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7891 {
7892         int i;
7893         float f1, f2, *c;
7894         float color4f[6*4];
7895
7896         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);
7897
7898         // this is only called once per entity so numsurfaces is always 1, and
7899         // surfacelist is always {0}, so this code does not handle batches
7900
7901         if (rsurface.ent_flags & RENDER_ADDITIVE)
7902         {
7903                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7904                 GL_DepthMask(false);
7905         }
7906         else if (rsurface.colormod[3] < 1)
7907         {
7908                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7909                 GL_DepthMask(false);
7910         }
7911         else
7912         {
7913                 GL_BlendFunc(GL_ONE, GL_ZERO);
7914                 GL_DepthMask(true);
7915         }
7916         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7917         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7918         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7919         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7920         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7921         for (i = 0, c = color4f;i < 6;i++, c += 4)
7922         {
7923                 c[0] *= rsurface.colormod[0];
7924                 c[1] *= rsurface.colormod[1];
7925                 c[2] *= rsurface.colormod[2];
7926                 c[3] *= rsurface.colormod[3];
7927         }
7928         if (r_refdef.fogenabled)
7929         {
7930                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7931                 {
7932                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7933                         f2 = 1 - f1;
7934                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7935                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7936                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7937                 }
7938         }
7939 //      R_Mesh_ResetTextureState();
7940         R_SetupShader_Generic_NoTexture(false, false);
7941         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7942         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7943 }
7944
7945 void R_DrawNoModel(entity_render_t *ent)
7946 {
7947         vec3_t org;
7948         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7949         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7950                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7951         else
7952                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7953 }
7954
7955 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7956 {
7957         vec3_t right1, right2, diff, normal;
7958
7959         VectorSubtract (org2, org1, normal);
7960
7961         // calculate 'right' vector for start
7962         VectorSubtract (r_refdef.view.origin, org1, diff);
7963         CrossProduct (normal, diff, right1);
7964         VectorNormalize (right1);
7965
7966         // calculate 'right' vector for end
7967         VectorSubtract (r_refdef.view.origin, org2, diff);
7968         CrossProduct (normal, diff, right2);
7969         VectorNormalize (right2);
7970
7971         vert[ 0] = org1[0] + width * right1[0];
7972         vert[ 1] = org1[1] + width * right1[1];
7973         vert[ 2] = org1[2] + width * right1[2];
7974         vert[ 3] = org1[0] - width * right1[0];
7975         vert[ 4] = org1[1] - width * right1[1];
7976         vert[ 5] = org1[2] - width * right1[2];
7977         vert[ 6] = org2[0] - width * right2[0];
7978         vert[ 7] = org2[1] - width * right2[1];
7979         vert[ 8] = org2[2] - width * right2[2];
7980         vert[ 9] = org2[0] + width * right2[0];
7981         vert[10] = org2[1] + width * right2[1];
7982         vert[11] = org2[2] + width * right2[2];
7983 }
7984
7985 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)
7986 {
7987         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7988         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7989         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7990         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7991         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7992         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7993         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7994         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7995         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7996         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7997         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7998         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7999 }
8000
8001 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8002 {
8003         int i;
8004         float *vertex3f;
8005         float v[3];
8006         VectorSet(v, x, y, z);
8007         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8008                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8009                         break;
8010         if (i == mesh->numvertices)
8011         {
8012                 if (mesh->numvertices < mesh->maxvertices)
8013                 {
8014                         VectorCopy(v, vertex3f);
8015                         mesh->numvertices++;
8016                 }
8017                 return mesh->numvertices;
8018         }
8019         else
8020                 return i;
8021 }
8022
8023 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8024 {
8025         int i;
8026         int *e, element[3];
8027         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8028         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8029         e = mesh->element3i + mesh->numtriangles * 3;
8030         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8031         {
8032                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8033                 if (mesh->numtriangles < mesh->maxtriangles)
8034                 {
8035                         *e++ = element[0];
8036                         *e++ = element[1];
8037                         *e++ = element[2];
8038                         mesh->numtriangles++;
8039                 }
8040                 element[1] = element[2];
8041         }
8042 }
8043
8044 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8045 {
8046         int i;
8047         int *e, element[3];
8048         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8049         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8050         e = mesh->element3i + mesh->numtriangles * 3;
8051         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8052         {
8053                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8054                 if (mesh->numtriangles < mesh->maxtriangles)
8055                 {
8056                         *e++ = element[0];
8057                         *e++ = element[1];
8058                         *e++ = element[2];
8059                         mesh->numtriangles++;
8060                 }
8061                 element[1] = element[2];
8062         }
8063 }
8064
8065 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8066 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8067 {
8068         int planenum, planenum2;
8069         int w;
8070         int tempnumpoints;
8071         mplane_t *plane, *plane2;
8072         double maxdist;
8073         double temppoints[2][256*3];
8074         // figure out how large a bounding box we need to properly compute this brush
8075         maxdist = 0;
8076         for (w = 0;w < numplanes;w++)
8077                 maxdist = max(maxdist, fabs(planes[w].dist));
8078         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8079         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8080         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8081         {
8082                 w = 0;
8083                 tempnumpoints = 4;
8084                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8085                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8086                 {
8087                         if (planenum2 == planenum)
8088                                 continue;
8089                         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);
8090                         w = !w;
8091                 }
8092                 if (tempnumpoints < 3)
8093                         continue;
8094                 // generate elements forming a triangle fan for this polygon
8095                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8096         }
8097 }
8098
8099 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)
8100 {
8101         texturelayer_t *layer;
8102         layer = t->currentlayers + t->currentnumlayers++;
8103         layer->type = type;
8104         layer->depthmask = depthmask;
8105         layer->blendfunc1 = blendfunc1;
8106         layer->blendfunc2 = blendfunc2;
8107         layer->texture = texture;
8108         layer->texmatrix = *matrix;
8109         layer->color[0] = r;
8110         layer->color[1] = g;
8111         layer->color[2] = b;
8112         layer->color[3] = a;
8113 }
8114
8115 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8116 {
8117         if(parms[0] == 0 && parms[1] == 0)
8118                 return false;
8119         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8120                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8121                         return false;
8122         return true;
8123 }
8124
8125 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8126 {
8127         double index, f;
8128         index = parms[2] + rsurface.shadertime * parms[3];
8129         index -= floor(index);
8130         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8131         {
8132         default:
8133         case Q3WAVEFUNC_NONE:
8134         case Q3WAVEFUNC_NOISE:
8135         case Q3WAVEFUNC_COUNT:
8136                 f = 0;
8137                 break;
8138         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8139         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8140         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8141         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8142         case Q3WAVEFUNC_TRIANGLE:
8143                 index *= 4;
8144                 f = index - floor(index);
8145                 if (index < 1)
8146                 {
8147                         // f = f;
8148                 }
8149                 else if (index < 2)
8150                         f = 1 - f;
8151                 else if (index < 3)
8152                         f = -f;
8153                 else
8154                         f = -(1 - f);
8155                 break;
8156         }
8157         f = parms[0] + parms[1] * f;
8158         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8159                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8160         return (float) f;
8161 }
8162
8163 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8164 {
8165         int w, h, idx;
8166         float shadertime;
8167         float f;
8168         float offsetd[2];
8169         float tcmat[12];
8170         matrix4x4_t matrix, temp;
8171         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8172         // it's better to have one huge fixup every 9 hours than gradual
8173         // degradation over time which looks consistently bad after many hours.
8174         //
8175         // tcmod scroll in particular suffers from this degradation which can't be
8176         // effectively worked around even with floor() tricks because we don't
8177         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8178         // a workaround involving floor() would be incorrect anyway...
8179         shadertime = rsurface.shadertime;
8180         if (shadertime >= 32768.0f)
8181                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8182         switch(tcmod->tcmod)
8183         {
8184                 case Q3TCMOD_COUNT:
8185                 case Q3TCMOD_NONE:
8186                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8187                                 matrix = r_waterscrollmatrix;
8188                         else
8189                                 matrix = identitymatrix;
8190                         break;
8191                 case Q3TCMOD_ENTITYTRANSLATE:
8192                         // this is used in Q3 to allow the gamecode to control texcoord
8193                         // scrolling on the entity, which is not supported in darkplaces yet.
8194                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8195                         break;
8196                 case Q3TCMOD_ROTATE:
8197                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8198                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8199                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8200                         break;
8201                 case Q3TCMOD_SCALE:
8202                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8203                         break;
8204                 case Q3TCMOD_SCROLL:
8205                         // this particular tcmod is a "bug for bug" compatible one with regards to
8206                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8207                         // specifically did the wrapping and so we must mimic that...
8208                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8209                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8210                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8211                         break;
8212                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8213                         w = (int) tcmod->parms[0];
8214                         h = (int) tcmod->parms[1];
8215                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8216                         f = f - floor(f);
8217                         idx = (int) floor(f * w * h);
8218                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8219                         break;
8220                 case Q3TCMOD_STRETCH:
8221                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8222                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8223                         break;
8224                 case Q3TCMOD_TRANSFORM:
8225                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8226                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8227                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8228                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8229                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8230                         break;
8231                 case Q3TCMOD_TURBULENT:
8232                         // this is handled in the RSurf_PrepareVertices function
8233                         matrix = identitymatrix;
8234                         break;
8235         }
8236         temp = *texmatrix;
8237         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8238 }
8239
8240 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8241 {
8242         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8243         char name[MAX_QPATH];
8244         skinframe_t *skinframe;
8245         unsigned char pixels[296*194];
8246         strlcpy(cache->name, skinname, sizeof(cache->name));
8247         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8248         if (developer_loading.integer)
8249                 Con_Printf("loading %s\n", name);
8250         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8251         if (!skinframe || !skinframe->base)
8252         {
8253                 unsigned char *f;
8254                 fs_offset_t filesize;
8255                 skinframe = NULL;
8256                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8257                 if (f)
8258                 {
8259                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8260                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8261                         Mem_Free(f);
8262                 }
8263         }
8264         cache->skinframe = skinframe;
8265 }
8266
8267 texture_t *R_GetCurrentTexture(texture_t *t)
8268 {
8269         int i;
8270         const entity_render_t *ent = rsurface.entity;
8271         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8272         q3shaderinfo_layer_tcmod_t *tcmod;
8273
8274         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8275                 return t->currentframe;
8276         t->update_lastrenderframe = r_textureframe;
8277         t->update_lastrenderentity = (void *)ent;
8278
8279         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8280                 t->camera_entity = ent->entitynumber;
8281         else
8282                 t->camera_entity = 0;
8283
8284         // switch to an alternate material if this is a q1bsp animated material
8285         {
8286                 texture_t *texture = t;
8287                 int s = rsurface.ent_skinnum;
8288                 if ((unsigned int)s >= (unsigned int)model->numskins)
8289                         s = 0;
8290                 if (model->skinscenes)
8291                 {
8292                         if (model->skinscenes[s].framecount > 1)
8293                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8294                         else
8295                                 s = model->skinscenes[s].firstframe;
8296                 }
8297                 if (s > 0)
8298                         t = t + s * model->num_surfaces;
8299                 if (t->animated)
8300                 {
8301                         // use an alternate animation if the entity's frame is not 0,
8302                         // and only if the texture has an alternate animation
8303                         if (t->animated == 2) // q2bsp
8304                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8305                         else if (rsurface.ent_alttextures && t->anim_total[1])
8306                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8307                         else
8308                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8309                 }
8310                 texture->currentframe = t;
8311         }
8312
8313         // update currentskinframe to be a qw skin or animation frame
8314         if (rsurface.ent_qwskin >= 0)
8315         {
8316                 i = rsurface.ent_qwskin;
8317                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8318                 {
8319                         r_qwskincache_size = cl.maxclients;
8320                         if (r_qwskincache)
8321                                 Mem_Free(r_qwskincache);
8322                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8323                 }
8324                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8325                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8326                 t->currentskinframe = r_qwskincache[i].skinframe;
8327                 if (t->materialshaderpass && t->currentskinframe == NULL)
8328                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8329         }
8330         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8331                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8332         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8333                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8334
8335         t->currentmaterialflags = t->basematerialflags;
8336         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8337         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8338                 t->currentalpha *= r_wateralpha.value;
8339         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8340                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8341         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8342                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8343         if (!(rsurface.ent_flags & RENDER_LIGHT))
8344                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8345         else if (FAKELIGHT_ENABLED)
8346         {
8347                 // no modellight if using fakelight for the map
8348         }
8349         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8350         {
8351                 // pick a model lighting mode
8352                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8353                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8354                 else
8355                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8356         }
8357         if (rsurface.ent_flags & RENDER_ADDITIVE)
8358                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8359         else if (t->currentalpha < 1)
8360                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8361         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8362         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8363                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8364         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8365                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8366         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8367                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8368         if (t->backgroundshaderpass)
8369                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8370         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8371         {
8372                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8373                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8374         }
8375         else
8376                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8377         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8378         {
8379                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8380                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8381         }
8382         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8383                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8384
8385         // there is no tcmod
8386         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8387         {
8388                 t->currenttexmatrix = r_waterscrollmatrix;
8389                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8390         }
8391         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8392         {
8393                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8394                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8395         }
8396
8397         if (t->materialshaderpass)
8398                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8399                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8400
8401         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8402         if (t->currentskinframe->qpixels)
8403                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8404         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8405         if (!t->basetexture)
8406                 t->basetexture = r_texture_notexture;
8407         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8408         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8409         t->nmaptexture = t->currentskinframe->nmap;
8410         if (!t->nmaptexture)
8411                 t->nmaptexture = r_texture_blanknormalmap;
8412         t->glosstexture = r_texture_black;
8413         t->glowtexture = t->currentskinframe->glow;
8414         t->fogtexture = t->currentskinframe->fog;
8415         t->reflectmasktexture = t->currentskinframe->reflect;
8416         if (t->backgroundshaderpass)
8417         {
8418                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8419                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8420                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8421                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8422                 t->backgroundglosstexture = r_texture_black;
8423                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8424                 if (!t->backgroundnmaptexture)
8425                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8426                 // make sure that if glow is going to be used, both textures are not NULL
8427                 if (!t->backgroundglowtexture && t->glowtexture)
8428                         t->backgroundglowtexture = r_texture_black;
8429                 if (!t->glowtexture && t->backgroundglowtexture)
8430                         t->glowtexture = r_texture_black;
8431         }
8432         else
8433         {
8434                 t->backgroundbasetexture = r_texture_white;
8435                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8436                 t->backgroundglosstexture = r_texture_black;
8437                 t->backgroundglowtexture = NULL;
8438         }
8439         t->specularpower = r_shadow_glossexponent.value;
8440         // TODO: store reference values for these in the texture?
8441         t->specularscale = 0;
8442         if (r_shadow_gloss.integer > 0)
8443         {
8444                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8445                 {
8446                         if (r_shadow_glossintensity.value > 0)
8447                         {
8448                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8449                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8450                                 t->specularscale = r_shadow_glossintensity.value;
8451                         }
8452                 }
8453                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8454                 {
8455                         t->glosstexture = r_texture_white;
8456                         t->backgroundglosstexture = r_texture_white;
8457                         t->specularscale = r_shadow_gloss2intensity.value;
8458                         t->specularpower = r_shadow_gloss2exponent.value;
8459                 }
8460         }
8461         t->specularscale *= t->specularscalemod;
8462         t->specularpower *= t->specularpowermod;
8463         t->rtlightambient = 0;
8464
8465         // lightmaps mode looks bad with dlights using actual texturing, so turn
8466         // off the colormap and glossmap, but leave the normalmap on as it still
8467         // accurately represents the shading involved
8468         if (gl_lightmaps.integer)
8469         {
8470                 t->basetexture = r_texture_grey128;
8471                 t->pantstexture = r_texture_black;
8472                 t->shirttexture = r_texture_black;
8473                 if (gl_lightmaps.integer < 2)
8474                         t->nmaptexture = r_texture_blanknormalmap;
8475                 t->glosstexture = r_texture_black;
8476                 t->glowtexture = NULL;
8477                 t->fogtexture = NULL;
8478                 t->reflectmasktexture = NULL;
8479                 t->backgroundbasetexture = NULL;
8480                 if (gl_lightmaps.integer < 2)
8481                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8482                 t->backgroundglosstexture = r_texture_black;
8483                 t->backgroundglowtexture = NULL;
8484                 t->specularscale = 0;
8485                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8486         }
8487
8488         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8489         VectorClear(t->dlightcolor);
8490         t->currentnumlayers = 0;
8491         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8492         {
8493                 int blendfunc1, blendfunc2;
8494                 qboolean depthmask;
8495                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8496                 {
8497                         blendfunc1 = GL_SRC_ALPHA;
8498                         blendfunc2 = GL_ONE;
8499                 }
8500                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8501                 {
8502                         blendfunc1 = GL_SRC_ALPHA;
8503                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8504                 }
8505                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8506                 {
8507                         blendfunc1 = t->customblendfunc[0];
8508                         blendfunc2 = t->customblendfunc[1];
8509                 }
8510                 else
8511                 {
8512                         blendfunc1 = GL_ONE;
8513                         blendfunc2 = GL_ZERO;
8514                 }
8515                 // don't colormod evilblend textures
8516                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8517                         VectorSet(t->lightmapcolor, 1, 1, 1);
8518                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8519                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8520                 {
8521                         // fullbright is not affected by r_refdef.lightmapintensity
8522                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8523                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8524                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8525                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8526                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8527                 }
8528                 else
8529                 {
8530                         vec3_t ambientcolor;
8531                         float colorscale;
8532                         // set the color tint used for lights affecting this surface
8533                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8534                         colorscale = 2;
8535                         // q3bsp has no lightmap updates, so the lightstylevalue that
8536                         // would normally be baked into the lightmap must be
8537                         // applied to the color
8538                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8539                         if (model->type == mod_brushq3)
8540                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8541                         colorscale *= r_refdef.lightmapintensity;
8542                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8543                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8544                         // basic lit geometry
8545                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8546                         // add pants/shirt if needed
8547                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8548                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8549                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8550                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8551                         // now add ambient passes if needed
8552                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8553                         {
8554                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8555                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8556                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8557                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8558                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8559                         }
8560                 }
8561                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8562                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8563                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8564                 {
8565                         // if this is opaque use alpha blend which will darken the earlier
8566                         // passes cheaply.
8567                         //
8568                         // if this is an alpha blended material, all the earlier passes
8569                         // were darkened by fog already, so we only need to add the fog
8570                         // color ontop through the fog mask texture
8571                         //
8572                         // if this is an additive blended material, all the earlier passes
8573                         // were darkened by fog already, and we should not add fog color
8574                         // (because the background was not darkened, there is no fog color
8575                         // that was lost behind it).
8576                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8577                 }
8578         }
8579
8580         return t;
8581 }
8582
8583 rsurfacestate_t rsurface;
8584
8585 void RSurf_ActiveWorldEntity(void)
8586 {
8587         dp_model_t *model = r_refdef.scene.worldmodel;
8588         //if (rsurface.entity == r_refdef.scene.worldentity)
8589         //      return;
8590         rsurface.entity = r_refdef.scene.worldentity;
8591         rsurface.skeleton = NULL;
8592         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8593         rsurface.ent_skinnum = 0;
8594         rsurface.ent_qwskin = -1;
8595         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8596         rsurface.shadertime = r_refdef.scene.time;
8597         rsurface.matrix = identitymatrix;
8598         rsurface.inversematrix = identitymatrix;
8599         rsurface.matrixscale = 1;
8600         rsurface.inversematrixscale = 1;
8601         R_EntityMatrix(&identitymatrix);
8602         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8603         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8604         rsurface.fograngerecip = r_refdef.fograngerecip;
8605         rsurface.fogheightfade = r_refdef.fogheightfade;
8606         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8607         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8608         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8609         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8610         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8611         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8612         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8613         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8614         rsurface.colormod[3] = 1;
8615         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8616         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8617         rsurface.frameblend[0].lerp = 1;
8618         rsurface.ent_alttextures = false;
8619         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8620         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8621         rsurface.entityskeletaltransform3x4 = NULL;
8622         rsurface.entityskeletaltransform3x4buffer = NULL;
8623         rsurface.entityskeletaltransform3x4offset = 0;
8624         rsurface.entityskeletaltransform3x4size = 0;;
8625         rsurface.entityskeletalnumtransforms = 0;
8626         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8627         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8628         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8629         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8630         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8631         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8632         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8633         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8634         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8635         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8636         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8637         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8638         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8639         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8640         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8641         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8642         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8644         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8645         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8647         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8648         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8649         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8650         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8651         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8652         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8653         rsurface.modelelement3i = model->surfmesh.data_element3i;
8654         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8655         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8656         rsurface.modelelement3s = model->surfmesh.data_element3s;
8657         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8658         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8659         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8660         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8661         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8662         rsurface.modelsurfaces = model->data_surfaces;
8663         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8664         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8665         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8666         rsurface.modelgeneratedvertex = false;
8667         rsurface.batchgeneratedvertex = false;
8668         rsurface.batchfirstvertex = 0;
8669         rsurface.batchnumvertices = 0;
8670         rsurface.batchfirsttriangle = 0;
8671         rsurface.batchnumtriangles = 0;
8672         rsurface.batchvertex3f  = NULL;
8673         rsurface.batchvertex3f_vertexbuffer = NULL;
8674         rsurface.batchvertex3f_bufferoffset = 0;
8675         rsurface.batchsvector3f = NULL;
8676         rsurface.batchsvector3f_vertexbuffer = NULL;
8677         rsurface.batchsvector3f_bufferoffset = 0;
8678         rsurface.batchtvector3f = NULL;
8679         rsurface.batchtvector3f_vertexbuffer = NULL;
8680         rsurface.batchtvector3f_bufferoffset = 0;
8681         rsurface.batchnormal3f  = NULL;
8682         rsurface.batchnormal3f_vertexbuffer = NULL;
8683         rsurface.batchnormal3f_bufferoffset = 0;
8684         rsurface.batchlightmapcolor4f = NULL;
8685         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8686         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8687         rsurface.batchtexcoordtexture2f = NULL;
8688         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8689         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8690         rsurface.batchtexcoordlightmap2f = NULL;
8691         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8692         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8693         rsurface.batchskeletalindex4ub = NULL;
8694         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8695         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8696         rsurface.batchskeletalweight4ub = NULL;
8697         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8698         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8699         rsurface.batchvertexmesh = NULL;
8700         rsurface.batchvertexmesh_vertexbuffer = NULL;
8701         rsurface.batchvertexmesh_bufferoffset = 0;
8702         rsurface.batchelement3i = NULL;
8703         rsurface.batchelement3i_indexbuffer = NULL;
8704         rsurface.batchelement3i_bufferoffset = 0;
8705         rsurface.batchelement3s = NULL;
8706         rsurface.batchelement3s_indexbuffer = NULL;
8707         rsurface.batchelement3s_bufferoffset = 0;
8708         rsurface.passcolor4f = NULL;
8709         rsurface.passcolor4f_vertexbuffer = NULL;
8710         rsurface.passcolor4f_bufferoffset = 0;
8711         rsurface.forcecurrenttextureupdate = false;
8712 }
8713
8714 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8715 {
8716         dp_model_t *model = ent->model;
8717         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8718         //      return;
8719         rsurface.entity = (entity_render_t *)ent;
8720         rsurface.skeleton = ent->skeleton;
8721         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8722         rsurface.ent_skinnum = ent->skinnum;
8723         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;
8724         rsurface.ent_flags = ent->flags;
8725         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8726         rsurface.matrix = ent->matrix;
8727         rsurface.inversematrix = ent->inversematrix;
8728         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8729         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8730         R_EntityMatrix(&rsurface.matrix);
8731         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8732         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8733         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8734         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8735         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8736         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8737         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8738         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8739         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8740         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8741         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8742         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8743         rsurface.colormod[3] = ent->alpha;
8744         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8745         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8746         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8747         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8748         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8749         if (ent->model->brush.submodel && !prepass)
8750         {
8751                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8752                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8753         }
8754         // if the animcache code decided it should use the shader path, skip the deform step
8755         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8756         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8757         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8758         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8759         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8760         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8761         {
8762                 if (ent->animcache_vertex3f)
8763                 {
8764                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8765                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8766                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8767                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8768                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8769                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8770                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8771                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8772                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8773                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8774                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8775                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8776                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8777                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8778                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8779                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8780                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8781                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8782                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8783                 }
8784                 else if (wanttangents)
8785                 {
8786                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8787                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8788                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8789                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8790                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8791                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8792                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8793                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8794                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8795                         rsurface.modelvertexmesh = NULL;
8796                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8797                         rsurface.modelvertexmesh_bufferoffset = 0;
8798                         rsurface.modelvertex3f_vertexbuffer = NULL;
8799                         rsurface.modelvertex3f_bufferoffset = 0;
8800                         rsurface.modelvertex3f_vertexbuffer = 0;
8801                         rsurface.modelvertex3f_bufferoffset = 0;
8802                         rsurface.modelsvector3f_vertexbuffer = 0;
8803                         rsurface.modelsvector3f_bufferoffset = 0;
8804                         rsurface.modeltvector3f_vertexbuffer = 0;
8805                         rsurface.modeltvector3f_bufferoffset = 0;
8806                         rsurface.modelnormal3f_vertexbuffer = 0;
8807                         rsurface.modelnormal3f_bufferoffset = 0;
8808                 }
8809                 else if (wantnormals)
8810                 {
8811                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8812                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8813                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8814                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8815                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8816                         rsurface.modelsvector3f = NULL;
8817                         rsurface.modeltvector3f = NULL;
8818                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8819                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8820                         rsurface.modelvertexmesh = NULL;
8821                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8822                         rsurface.modelvertexmesh_bufferoffset = 0;
8823                         rsurface.modelvertex3f_vertexbuffer = NULL;
8824                         rsurface.modelvertex3f_bufferoffset = 0;
8825                         rsurface.modelvertex3f_vertexbuffer = 0;
8826                         rsurface.modelvertex3f_bufferoffset = 0;
8827                         rsurface.modelsvector3f_vertexbuffer = 0;
8828                         rsurface.modelsvector3f_bufferoffset = 0;
8829                         rsurface.modeltvector3f_vertexbuffer = 0;
8830                         rsurface.modeltvector3f_bufferoffset = 0;
8831                         rsurface.modelnormal3f_vertexbuffer = 0;
8832                         rsurface.modelnormal3f_bufferoffset = 0;
8833                 }
8834                 else
8835                 {
8836                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8837                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8838                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8839                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8840                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8841                         rsurface.modelsvector3f = NULL;
8842                         rsurface.modeltvector3f = NULL;
8843                         rsurface.modelnormal3f = NULL;
8844                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8845                         rsurface.modelvertexmesh = NULL;
8846                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8847                         rsurface.modelvertexmesh_bufferoffset = 0;
8848                         rsurface.modelvertex3f_vertexbuffer = NULL;
8849                         rsurface.modelvertex3f_bufferoffset = 0;
8850                         rsurface.modelvertex3f_vertexbuffer = 0;
8851                         rsurface.modelvertex3f_bufferoffset = 0;
8852                         rsurface.modelsvector3f_vertexbuffer = 0;
8853                         rsurface.modelsvector3f_bufferoffset = 0;
8854                         rsurface.modeltvector3f_vertexbuffer = 0;
8855                         rsurface.modeltvector3f_bufferoffset = 0;
8856                         rsurface.modelnormal3f_vertexbuffer = 0;
8857                         rsurface.modelnormal3f_bufferoffset = 0;
8858                 }
8859                 rsurface.modelgeneratedvertex = true;
8860         }
8861         else
8862         {
8863                 if (rsurface.entityskeletaltransform3x4)
8864                 {
8865                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8866                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8867                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8868                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8869                 }
8870                 else
8871                 {
8872                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8873                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8874                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8875                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8876                 }
8877                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8878                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8879                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8880                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8881                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8882                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8883                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8884                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8885                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8886                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8887                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8888                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8889                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8890                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8891                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8892                 rsurface.modelgeneratedvertex = false;
8893         }
8894         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8895         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8896         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8897         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8898         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8899         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8900         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8901         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8902         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8903         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8904         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8905         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8906         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8907         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8908         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8909         rsurface.modelelement3i = model->surfmesh.data_element3i;
8910         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8911         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8912         rsurface.modelelement3s = model->surfmesh.data_element3s;
8913         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8914         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8915         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8916         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8917         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8918         rsurface.modelsurfaces = model->data_surfaces;
8919         rsurface.batchgeneratedvertex = false;
8920         rsurface.batchfirstvertex = 0;
8921         rsurface.batchnumvertices = 0;
8922         rsurface.batchfirsttriangle = 0;
8923         rsurface.batchnumtriangles = 0;
8924         rsurface.batchvertex3f  = NULL;
8925         rsurface.batchvertex3f_vertexbuffer = NULL;
8926         rsurface.batchvertex3f_bufferoffset = 0;
8927         rsurface.batchsvector3f = NULL;
8928         rsurface.batchsvector3f_vertexbuffer = NULL;
8929         rsurface.batchsvector3f_bufferoffset = 0;
8930         rsurface.batchtvector3f = NULL;
8931         rsurface.batchtvector3f_vertexbuffer = NULL;
8932         rsurface.batchtvector3f_bufferoffset = 0;
8933         rsurface.batchnormal3f  = NULL;
8934         rsurface.batchnormal3f_vertexbuffer = NULL;
8935         rsurface.batchnormal3f_bufferoffset = 0;
8936         rsurface.batchlightmapcolor4f = NULL;
8937         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8938         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8939         rsurface.batchtexcoordtexture2f = NULL;
8940         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8941         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8942         rsurface.batchtexcoordlightmap2f = NULL;
8943         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8944         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8945         rsurface.batchskeletalindex4ub = NULL;
8946         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8947         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8948         rsurface.batchskeletalweight4ub = NULL;
8949         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8950         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8951         rsurface.batchvertexmesh = NULL;
8952         rsurface.batchvertexmesh_vertexbuffer = NULL;
8953         rsurface.batchvertexmesh_bufferoffset = 0;
8954         rsurface.batchelement3i = NULL;
8955         rsurface.batchelement3i_indexbuffer = NULL;
8956         rsurface.batchelement3i_bufferoffset = 0;
8957         rsurface.batchelement3s = NULL;
8958         rsurface.batchelement3s_indexbuffer = NULL;
8959         rsurface.batchelement3s_bufferoffset = 0;
8960         rsurface.passcolor4f = NULL;
8961         rsurface.passcolor4f_vertexbuffer = NULL;
8962         rsurface.passcolor4f_bufferoffset = 0;
8963         rsurface.forcecurrenttextureupdate = false;
8964 }
8965
8966 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)
8967 {
8968         rsurface.entity = r_refdef.scene.worldentity;
8969         rsurface.skeleton = NULL;
8970         rsurface.ent_skinnum = 0;
8971         rsurface.ent_qwskin = -1;
8972         rsurface.ent_flags = entflags;
8973         rsurface.shadertime = r_refdef.scene.time - shadertime;
8974         rsurface.modelnumvertices = numvertices;
8975         rsurface.modelnumtriangles = numtriangles;
8976         rsurface.matrix = *matrix;
8977         rsurface.inversematrix = *inversematrix;
8978         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8979         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8980         R_EntityMatrix(&rsurface.matrix);
8981         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8982         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8983         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8984         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8985         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8986         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8987         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8988         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8989         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8990         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8991         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8992         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8993         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8994         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8995         rsurface.frameblend[0].lerp = 1;
8996         rsurface.ent_alttextures = false;
8997         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8998         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8999         rsurface.entityskeletaltransform3x4 = NULL;
9000         rsurface.entityskeletaltransform3x4buffer = NULL;
9001         rsurface.entityskeletaltransform3x4offset = 0;
9002         rsurface.entityskeletaltransform3x4size = 0;
9003         rsurface.entityskeletalnumtransforms = 0;
9004         r_refdef.stats[r_stat_batch_entitycustom_count]++;
9005         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9006         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9007         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9008         if (wanttangents)
9009         {
9010                 rsurface.modelvertex3f = (float *)vertex3f;
9011                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9012                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9013                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9014         }
9015         else if (wantnormals)
9016         {
9017                 rsurface.modelvertex3f = (float *)vertex3f;
9018                 rsurface.modelsvector3f = NULL;
9019                 rsurface.modeltvector3f = NULL;
9020                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9021         }
9022         else
9023         {
9024                 rsurface.modelvertex3f = (float *)vertex3f;
9025                 rsurface.modelsvector3f = NULL;
9026                 rsurface.modeltvector3f = NULL;
9027                 rsurface.modelnormal3f = NULL;
9028         }
9029         rsurface.modelvertexmesh = NULL;
9030         rsurface.modelvertexmesh_vertexbuffer = NULL;
9031         rsurface.modelvertexmesh_bufferoffset = 0;
9032         rsurface.modelvertex3f_vertexbuffer = 0;
9033         rsurface.modelvertex3f_bufferoffset = 0;
9034         rsurface.modelsvector3f_vertexbuffer = 0;
9035         rsurface.modelsvector3f_bufferoffset = 0;
9036         rsurface.modeltvector3f_vertexbuffer = 0;
9037         rsurface.modeltvector3f_bufferoffset = 0;
9038         rsurface.modelnormal3f_vertexbuffer = 0;
9039         rsurface.modelnormal3f_bufferoffset = 0;
9040         rsurface.modelgeneratedvertex = true;
9041         rsurface.modellightmapcolor4f  = (float *)color4f;
9042         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9043         rsurface.modellightmapcolor4f_bufferoffset = 0;
9044         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
9045         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9046         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9047         rsurface.modeltexcoordlightmap2f  = NULL;
9048         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9049         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9050         rsurface.modelskeletalindex4ub = NULL;
9051         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9052         rsurface.modelskeletalindex4ub_bufferoffset = 0;
9053         rsurface.modelskeletalweight4ub = NULL;
9054         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9055         rsurface.modelskeletalweight4ub_bufferoffset = 0;
9056         rsurface.modelelement3i = (int *)element3i;
9057         rsurface.modelelement3i_indexbuffer = NULL;
9058         rsurface.modelelement3i_bufferoffset = 0;
9059         rsurface.modelelement3s = (unsigned short *)element3s;
9060         rsurface.modelelement3s_indexbuffer = NULL;
9061         rsurface.modelelement3s_bufferoffset = 0;
9062         rsurface.modellightmapoffsets = NULL;
9063         rsurface.modelsurfaces = NULL;
9064         rsurface.batchgeneratedvertex = false;
9065         rsurface.batchfirstvertex = 0;
9066         rsurface.batchnumvertices = 0;
9067         rsurface.batchfirsttriangle = 0;
9068         rsurface.batchnumtriangles = 0;
9069         rsurface.batchvertex3f  = NULL;
9070         rsurface.batchvertex3f_vertexbuffer = NULL;
9071         rsurface.batchvertex3f_bufferoffset = 0;
9072         rsurface.batchsvector3f = NULL;
9073         rsurface.batchsvector3f_vertexbuffer = NULL;
9074         rsurface.batchsvector3f_bufferoffset = 0;
9075         rsurface.batchtvector3f = NULL;
9076         rsurface.batchtvector3f_vertexbuffer = NULL;
9077         rsurface.batchtvector3f_bufferoffset = 0;
9078         rsurface.batchnormal3f  = NULL;
9079         rsurface.batchnormal3f_vertexbuffer = NULL;
9080         rsurface.batchnormal3f_bufferoffset = 0;
9081         rsurface.batchlightmapcolor4f = NULL;
9082         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9083         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9084         rsurface.batchtexcoordtexture2f = NULL;
9085         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9086         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9087         rsurface.batchtexcoordlightmap2f = NULL;
9088         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9089         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9090         rsurface.batchskeletalindex4ub = NULL;
9091         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9092         rsurface.batchskeletalindex4ub_bufferoffset = 0;
9093         rsurface.batchskeletalweight4ub = NULL;
9094         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9095         rsurface.batchskeletalweight4ub_bufferoffset = 0;
9096         rsurface.batchvertexmesh = NULL;
9097         rsurface.batchvertexmesh_vertexbuffer = NULL;
9098         rsurface.batchvertexmesh_bufferoffset = 0;
9099         rsurface.batchelement3i = NULL;
9100         rsurface.batchelement3i_indexbuffer = NULL;
9101         rsurface.batchelement3i_bufferoffset = 0;
9102         rsurface.batchelement3s = NULL;
9103         rsurface.batchelement3s_indexbuffer = NULL;
9104         rsurface.batchelement3s_bufferoffset = 0;
9105         rsurface.passcolor4f = NULL;
9106         rsurface.passcolor4f_vertexbuffer = NULL;
9107         rsurface.passcolor4f_bufferoffset = 0;
9108         rsurface.forcecurrenttextureupdate = true;
9109
9110         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9111         {
9112                 if ((wantnormals || wanttangents) && !normal3f)
9113                 {
9114                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9115                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9116                 }
9117                 if (wanttangents && !svector3f)
9118                 {
9119                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9120                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9121                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9122                 }
9123         }
9124 }
9125
9126 float RSurf_FogPoint(const float *v)
9127 {
9128         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9129         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9130         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9131         float FogHeightFade = r_refdef.fogheightfade;
9132         float fogfrac;
9133         unsigned int fogmasktableindex;
9134         if (r_refdef.fogplaneviewabove)
9135                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9136         else
9137                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9138         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9139         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9140 }
9141
9142 float RSurf_FogVertex(const float *v)
9143 {
9144         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9145         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9146         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9147         float FogHeightFade = rsurface.fogheightfade;
9148         float fogfrac;
9149         unsigned int fogmasktableindex;
9150         if (r_refdef.fogplaneviewabove)
9151                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9152         else
9153                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9154         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9155         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9156 }
9157
9158 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9159 {
9160         int i;
9161         for (i = 0;i < numelements;i++)
9162                 outelement3i[i] = inelement3i[i] + adjust;
9163 }
9164
9165 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9166 extern cvar_t gl_vbo;
9167 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9168 {
9169         int deformindex;
9170         int firsttriangle;
9171         int numtriangles;
9172         int firstvertex;
9173         int endvertex;
9174         int numvertices;
9175         int surfacefirsttriangle;
9176         int surfacenumtriangles;
9177         int surfacefirstvertex;
9178         int surfaceendvertex;
9179         int surfacenumvertices;
9180         int batchnumsurfaces = texturenumsurfaces;
9181         int batchnumvertices;
9182         int batchnumtriangles;
9183         int needsupdate;
9184         int i, j;
9185         qboolean gaps;
9186         qboolean dynamicvertex;
9187         float amplitude;
9188         float animpos;
9189         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9190         float waveparms[4];
9191         unsigned char *ub;
9192         q3shaderinfo_deform_t *deform;
9193         const msurface_t *surface, *firstsurface;
9194         r_vertexmesh_t *vertexmesh;
9195         if (!texturenumsurfaces)
9196                 return;
9197         // find vertex range of this surface batch
9198         gaps = false;
9199         firstsurface = texturesurfacelist[0];
9200         firsttriangle = firstsurface->num_firsttriangle;
9201         batchnumvertices = 0;
9202         batchnumtriangles = 0;
9203         firstvertex = endvertex = firstsurface->num_firstvertex;
9204         for (i = 0;i < texturenumsurfaces;i++)
9205         {
9206                 surface = texturesurfacelist[i];
9207                 if (surface != firstsurface + i)
9208                         gaps = true;
9209                 surfacefirstvertex = surface->num_firstvertex;
9210                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9211                 surfacenumvertices = surface->num_vertices;
9212                 surfacenumtriangles = surface->num_triangles;
9213                 if (firstvertex > surfacefirstvertex)
9214                         firstvertex = surfacefirstvertex;
9215                 if (endvertex < surfaceendvertex)
9216                         endvertex = surfaceendvertex;
9217                 batchnumvertices += surfacenumvertices;
9218                 batchnumtriangles += surfacenumtriangles;
9219         }
9220
9221         r_refdef.stats[r_stat_batch_batches]++;
9222         if (gaps)
9223                 r_refdef.stats[r_stat_batch_withgaps]++;
9224         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9225         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9226         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9227
9228         // we now know the vertex range used, and if there are any gaps in it
9229         rsurface.batchfirstvertex = firstvertex;
9230         rsurface.batchnumvertices = endvertex - firstvertex;
9231         rsurface.batchfirsttriangle = firsttriangle;
9232         rsurface.batchnumtriangles = batchnumtriangles;
9233
9234         // this variable holds flags for which properties have been updated that
9235         // may require regenerating vertexmesh array...
9236         needsupdate = 0;
9237
9238         // check if any dynamic vertex processing must occur
9239         dynamicvertex = false;
9240
9241         // a cvar to force the dynamic vertex path to be taken, for debugging
9242         if (r_batch_debugdynamicvertexpath.integer)
9243         {
9244                 if (!dynamicvertex)
9245                 {
9246                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9247                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9248                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9249                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9250                 }
9251                 dynamicvertex = true;
9252         }
9253
9254         // if there is a chance of animated vertex colors, it's a dynamic batch
9255         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9256         {
9257                 if (!dynamicvertex)
9258                 {
9259                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9260                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9261                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9262                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9263                 }
9264                 dynamicvertex = true;
9265                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9266         }
9267
9268         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9269         {
9270                 switch (deform->deform)
9271                 {
9272                 default:
9273                 case Q3DEFORM_PROJECTIONSHADOW:
9274                 case Q3DEFORM_TEXT0:
9275                 case Q3DEFORM_TEXT1:
9276                 case Q3DEFORM_TEXT2:
9277                 case Q3DEFORM_TEXT3:
9278                 case Q3DEFORM_TEXT4:
9279                 case Q3DEFORM_TEXT5:
9280                 case Q3DEFORM_TEXT6:
9281                 case Q3DEFORM_TEXT7:
9282                 case Q3DEFORM_NONE:
9283                         break;
9284                 case Q3DEFORM_AUTOSPRITE:
9285                         if (!dynamicvertex)
9286                         {
9287                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9288                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9289                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9290                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9291                         }
9292                         dynamicvertex = true;
9293                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9294                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9295                         break;
9296                 case Q3DEFORM_AUTOSPRITE2:
9297                         if (!dynamicvertex)
9298                         {
9299                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9300                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9301                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9302                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9303                         }
9304                         dynamicvertex = true;
9305                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9306                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9307                         break;
9308                 case Q3DEFORM_NORMAL:
9309                         if (!dynamicvertex)
9310                         {
9311                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9312                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9313                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9314                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9315                         }
9316                         dynamicvertex = true;
9317                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9318                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9319                         break;
9320                 case Q3DEFORM_WAVE:
9321                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9322                                 break; // if wavefunc is a nop, ignore this transform
9323                         if (!dynamicvertex)
9324                         {
9325                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9326                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9327                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9328                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9329                         }
9330                         dynamicvertex = true;
9331                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9332                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9333                         break;
9334                 case Q3DEFORM_BULGE:
9335                         if (!dynamicvertex)
9336                         {
9337                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9338                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9339                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9340                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9341                         }
9342                         dynamicvertex = true;
9343                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9344                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9345                         break;
9346                 case Q3DEFORM_MOVE:
9347                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9348                                 break; // if wavefunc is a nop, ignore this transform
9349                         if (!dynamicvertex)
9350                         {
9351                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9352                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9353                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9354                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9355                         }
9356                         dynamicvertex = true;
9357                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9358                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9359                         break;
9360                 }
9361         }
9362         if (rsurface.texture->materialshaderpass)
9363         {
9364                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9365                 {
9366                 default:
9367                 case Q3TCGEN_TEXTURE:
9368                         break;
9369                 case Q3TCGEN_LIGHTMAP:
9370                         if (!dynamicvertex)
9371                         {
9372                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9373                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9374                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9375                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9376                         }
9377                         dynamicvertex = true;
9378                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9379                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9380                         break;
9381                 case Q3TCGEN_VECTOR:
9382                         if (!dynamicvertex)
9383                         {
9384                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9385                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9386                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9387                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9388                         }
9389                         dynamicvertex = true;
9390                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9391                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9392                         break;
9393                 case Q3TCGEN_ENVIRONMENT:
9394                         if (!dynamicvertex)
9395                         {
9396                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9397                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9398                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9399                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9400                         }
9401                         dynamicvertex = true;
9402                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9403                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9404                         break;
9405                 }
9406                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9407                 {
9408                         if (!dynamicvertex)
9409                         {
9410                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9411                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9412                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9413                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9414                         }
9415                         dynamicvertex = true;
9416                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9417                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9418                 }
9419         }
9420
9421         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9422         {
9423                 if (!dynamicvertex)
9424                 {
9425                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9426                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9427                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9428                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9429                 }
9430                 dynamicvertex = true;
9431                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9432         }
9433
9434         // when the model data has no vertex buffer (dynamic mesh), we need to
9435         // eliminate gaps
9436         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9437                 batchneed |= BATCHNEED_NOGAPS;
9438
9439         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9440         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9441         // we ensure this by treating the vertex batch as dynamic...
9442         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9443         {
9444                 if (!dynamicvertex)
9445                 {
9446                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9447                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9448                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9449                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9450                 }
9451                 dynamicvertex = true;
9452         }
9453
9454         if (dynamicvertex)
9455         {
9456                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9457                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9458                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9459                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9460                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9461                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9462                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9463                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9464         }
9465
9466         // if needsupdate, we have to do a dynamic vertex batch for sure
9467         if (needsupdate & batchneed)
9468         {
9469                 if (!dynamicvertex)
9470                 {
9471                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9472                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9473                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9474                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9475                 }
9476                 dynamicvertex = true;
9477         }
9478
9479         // see if we need to build vertexmesh from arrays
9480         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9481         {
9482                 if (!dynamicvertex)
9483                 {
9484                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9485                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9486                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9487                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9488                 }
9489                 dynamicvertex = true;
9490         }
9491
9492         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9493         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9494                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9495
9496         rsurface.batchvertex3f = rsurface.modelvertex3f;
9497         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9498         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9499         rsurface.batchsvector3f = rsurface.modelsvector3f;
9500         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9501         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9502         rsurface.batchtvector3f = rsurface.modeltvector3f;
9503         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9504         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9505         rsurface.batchnormal3f = rsurface.modelnormal3f;
9506         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9507         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9508         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9509         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9510         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9511         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9512         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9513         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9514         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9515         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9516         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9517         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9518         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9519         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9520         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9521         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9522         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9523         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9524         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9525         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9526         rsurface.batchelement3i = rsurface.modelelement3i;
9527         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9528         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9529         rsurface.batchelement3s = rsurface.modelelement3s;
9530         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9531         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9532         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9533         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9534         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9535         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9536         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9537
9538         // if any dynamic vertex processing has to occur in software, we copy the
9539         // entire surface list together before processing to rebase the vertices
9540         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9541         //
9542         // if any gaps exist and we do not have a static vertex buffer, we have to
9543         // copy the surface list together to avoid wasting upload bandwidth on the
9544         // vertices in the gaps.
9545         //
9546         // if gaps exist and we have a static vertex buffer, we can choose whether
9547         // to combine the index buffer ranges into one dynamic index buffer or
9548         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9549         //
9550         // in many cases the batch is reduced to one draw call.
9551
9552         rsurface.batchmultidraw = false;
9553         rsurface.batchmultidrawnumsurfaces = 0;
9554         rsurface.batchmultidrawsurfacelist = NULL;
9555
9556         if (!dynamicvertex)
9557         {
9558                 // static vertex data, just set pointers...
9559                 rsurface.batchgeneratedvertex = false;
9560                 // if there are gaps, we want to build a combined index buffer,
9561                 // otherwise use the original static buffer with an appropriate offset
9562                 if (gaps)
9563                 {
9564                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9565                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9566                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9567                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9568                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9569                         {
9570                                 rsurface.batchmultidraw = true;
9571                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9572                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9573                                 return;
9574                         }
9575                         // build a new triangle elements array for this batch
9576                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9577                         rsurface.batchfirsttriangle = 0;
9578                         numtriangles = 0;
9579                         for (i = 0;i < texturenumsurfaces;i++)
9580                         {
9581                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9582                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9583                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9584                                 numtriangles += surfacenumtriangles;
9585                         }
9586                         rsurface.batchelement3i_indexbuffer = NULL;
9587                         rsurface.batchelement3i_bufferoffset = 0;
9588                         rsurface.batchelement3s = NULL;
9589                         rsurface.batchelement3s_indexbuffer = NULL;
9590                         rsurface.batchelement3s_bufferoffset = 0;
9591                         if (endvertex <= 65536)
9592                         {
9593                                 // make a 16bit (unsigned short) index array if possible
9594                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9595                                 for (i = 0;i < numtriangles*3;i++)
9596                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9597                         }
9598                         // upload buffer data for the copytriangles batch
9599                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9600                         {
9601                                 if (rsurface.batchelement3s)
9602                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9603                                 else if (rsurface.batchelement3i)
9604                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9605                         }
9606                 }
9607                 else
9608                 {
9609                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9610                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9611                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9612                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9613                 }
9614                 return;
9615         }
9616
9617         // something needs software processing, do it for real...
9618         // we only directly handle separate array data in this case and then
9619         // generate interleaved data if needed...
9620         rsurface.batchgeneratedvertex = true;
9621         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9622         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9623         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9624         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9625
9626         // now copy the vertex data into a combined array and make an index array
9627         // (this is what Quake3 does all the time)
9628         // we also apply any skeletal animation here that would have been done in
9629         // the vertex shader, because most of the dynamic vertex animation cases
9630         // need actual vertex positions and normals
9631         //if (dynamicvertex)
9632         {
9633                 rsurface.batchvertexmesh = NULL;
9634                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9635                 rsurface.batchvertexmesh_bufferoffset = 0;
9636                 rsurface.batchvertex3f = NULL;
9637                 rsurface.batchvertex3f_vertexbuffer = NULL;
9638                 rsurface.batchvertex3f_bufferoffset = 0;
9639                 rsurface.batchsvector3f = NULL;
9640                 rsurface.batchsvector3f_vertexbuffer = NULL;
9641                 rsurface.batchsvector3f_bufferoffset = 0;
9642                 rsurface.batchtvector3f = NULL;
9643                 rsurface.batchtvector3f_vertexbuffer = NULL;
9644                 rsurface.batchtvector3f_bufferoffset = 0;
9645                 rsurface.batchnormal3f = NULL;
9646                 rsurface.batchnormal3f_vertexbuffer = NULL;
9647                 rsurface.batchnormal3f_bufferoffset = 0;
9648                 rsurface.batchlightmapcolor4f = NULL;
9649                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9650                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9651                 rsurface.batchtexcoordtexture2f = NULL;
9652                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9653                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9654                 rsurface.batchtexcoordlightmap2f = NULL;
9655                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9656                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9657                 rsurface.batchskeletalindex4ub = NULL;
9658                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9659                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9660                 rsurface.batchskeletalweight4ub = NULL;
9661                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9662                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9663                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9664                 rsurface.batchelement3i_indexbuffer = NULL;
9665                 rsurface.batchelement3i_bufferoffset = 0;
9666                 rsurface.batchelement3s = NULL;
9667                 rsurface.batchelement3s_indexbuffer = NULL;
9668                 rsurface.batchelement3s_bufferoffset = 0;
9669                 rsurface.batchskeletaltransform3x4buffer = NULL;
9670                 rsurface.batchskeletaltransform3x4offset = 0;
9671                 rsurface.batchskeletaltransform3x4size = 0;
9672                 // we'll only be setting up certain arrays as needed
9673                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9674                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9675                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9676                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9677                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9678                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9679                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9680                 {
9681                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9682                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9683                 }
9684                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9685                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9686                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9687                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9688                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9689                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9690                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9691                 {
9692                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9693                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9694                 }
9695                 numvertices = 0;
9696                 numtriangles = 0;
9697                 for (i = 0;i < texturenumsurfaces;i++)
9698                 {
9699                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9700                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9701                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9702                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9703                         // copy only the data requested
9704                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9705                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9706                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9707                         {
9708                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9709                                 {
9710                                         if (rsurface.batchvertex3f)
9711                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9712                                         else
9713                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9714                                 }
9715                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9716                                 {
9717                                         if (rsurface.modelnormal3f)
9718                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9719                                         else
9720                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9721                                 }
9722                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9723                                 {
9724                                         if (rsurface.modelsvector3f)
9725                                         {
9726                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9727                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9728                                         }
9729                                         else
9730                                         {
9731                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9732                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9733                                         }
9734                                 }
9735                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9736                                 {
9737                                         if (rsurface.modellightmapcolor4f)
9738                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9739                                         else
9740                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9741                                 }
9742                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9743                                 {
9744                                         if (rsurface.modeltexcoordtexture2f)
9745                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9746                                         else
9747                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9748                                 }
9749                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9750                                 {
9751                                         if (rsurface.modeltexcoordlightmap2f)
9752                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9753                                         else
9754                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9755                                 }
9756                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9757                                 {
9758                                         if (rsurface.modelskeletalindex4ub)
9759                                         {
9760                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9761                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9762                                         }
9763                                         else
9764                                         {
9765                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9766                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9767                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9768                                                 for (j = 0;j < surfacenumvertices;j++)
9769                                                         ub[j*4] = 255;
9770                                         }
9771                                 }
9772                         }
9773                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9774                         numvertices += surfacenumvertices;
9775                         numtriangles += surfacenumtriangles;
9776                 }
9777
9778                 // generate a 16bit index array as well if possible
9779                 // (in general, dynamic batches fit)
9780                 if (numvertices <= 65536)
9781                 {
9782                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9783                         for (i = 0;i < numtriangles*3;i++)
9784                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9785                 }
9786
9787                 // since we've copied everything, the batch now starts at 0
9788                 rsurface.batchfirstvertex = 0;
9789                 rsurface.batchnumvertices = batchnumvertices;
9790                 rsurface.batchfirsttriangle = 0;
9791                 rsurface.batchnumtriangles = batchnumtriangles;
9792         }
9793
9794         // apply skeletal animation that would have been done in the vertex shader
9795         if (rsurface.batchskeletaltransform3x4)
9796         {
9797                 const unsigned char *si;
9798                 const unsigned char *sw;
9799                 const float *t[4];
9800                 const float *b = rsurface.batchskeletaltransform3x4;
9801                 float *vp, *vs, *vt, *vn;
9802                 float w[4];
9803                 float m[3][4], n[3][4];
9804                 float tp[3], ts[3], tt[3], tn[3];
9805                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9806                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9807                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9808                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9809                 si = rsurface.batchskeletalindex4ub;
9810                 sw = rsurface.batchskeletalweight4ub;
9811                 vp = rsurface.batchvertex3f;
9812                 vs = rsurface.batchsvector3f;
9813                 vt = rsurface.batchtvector3f;
9814                 vn = rsurface.batchnormal3f;
9815                 memset(m[0], 0, sizeof(m));
9816                 memset(n[0], 0, sizeof(n));
9817                 for (i = 0;i < batchnumvertices;i++)
9818                 {
9819                         t[0] = b + si[0]*12;
9820                         if (sw[0] == 255)
9821                         {
9822                                 // common case - only one matrix
9823                                 m[0][0] = t[0][ 0];
9824                                 m[0][1] = t[0][ 1];
9825                                 m[0][2] = t[0][ 2];
9826                                 m[0][3] = t[0][ 3];
9827                                 m[1][0] = t[0][ 4];
9828                                 m[1][1] = t[0][ 5];
9829                                 m[1][2] = t[0][ 6];
9830                                 m[1][3] = t[0][ 7];
9831                                 m[2][0] = t[0][ 8];
9832                                 m[2][1] = t[0][ 9];
9833                                 m[2][2] = t[0][10];
9834                                 m[2][3] = t[0][11];
9835                         }
9836                         else if (sw[2] + sw[3])
9837                         {
9838                                 // blend 4 matrices
9839                                 t[1] = b + si[1]*12;
9840                                 t[2] = b + si[2]*12;
9841                                 t[3] = b + si[3]*12;
9842                                 w[0] = sw[0] * (1.0f / 255.0f);
9843                                 w[1] = sw[1] * (1.0f / 255.0f);
9844                                 w[2] = sw[2] * (1.0f / 255.0f);
9845                                 w[3] = sw[3] * (1.0f / 255.0f);
9846                                 // blend the matrices
9847                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9848                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9849                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9850                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9851                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9852                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9853                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9854                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9855                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9856                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9857                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9858                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9859                         }
9860                         else
9861                         {
9862                                 // blend 2 matrices
9863                                 t[1] = b + si[1]*12;
9864                                 w[0] = sw[0] * (1.0f / 255.0f);
9865                                 w[1] = sw[1] * (1.0f / 255.0f);
9866                                 // blend the matrices
9867                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9868                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9869                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9870                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9871                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9872                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9873                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9874                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9875                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9876                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9877                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9878                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9879                         }
9880                         si += 4;
9881                         sw += 4;
9882                         // modify the vertex
9883                         VectorCopy(vp, tp);
9884                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9885                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9886                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9887                         vp += 3;
9888                         if (vn)
9889                         {
9890                                 // the normal transformation matrix is a set of cross products...
9891                                 CrossProduct(m[1], m[2], n[0]);
9892                                 CrossProduct(m[2], m[0], n[1]);
9893                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9894                                 VectorCopy(vn, tn);
9895                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9896                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9897                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9898                                 VectorNormalize(vn);
9899                                 vn += 3;
9900                                 if (vs)
9901                                 {
9902                                         VectorCopy(vs, ts);
9903                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9904                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9905                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9906                                         VectorNormalize(vs);
9907                                         vs += 3;
9908                                         VectorCopy(vt, tt);
9909                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9910                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9911                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9912                                         VectorNormalize(vt);
9913                                         vt += 3;
9914                                 }
9915                         }
9916                 }
9917                 rsurface.batchskeletaltransform3x4 = NULL;
9918                 rsurface.batchskeletalnumtransforms = 0;
9919         }
9920
9921         // q1bsp surfaces rendered in vertex color mode have to have colors
9922         // calculated based on lightstyles
9923         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9924         {
9925                 // generate color arrays for the surfaces in this list
9926                 int c[4];
9927                 int scale;
9928                 int size3;
9929                 const int *offsets;
9930                 const unsigned char *lm;
9931                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9932                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9933                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9934                 numvertices = 0;
9935                 for (i = 0;i < texturenumsurfaces;i++)
9936                 {
9937                         surface = texturesurfacelist[i];
9938                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9939                         surfacenumvertices = surface->num_vertices;
9940                         if (surface->lightmapinfo->samples)
9941                         {
9942                                 for (j = 0;j < surfacenumvertices;j++)
9943                                 {
9944                                         lm = surface->lightmapinfo->samples + offsets[j];
9945                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9946                                         VectorScale(lm, scale, c);
9947                                         if (surface->lightmapinfo->styles[1] != 255)
9948                                         {
9949                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9950                                                 lm += size3;
9951                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9952                                                 VectorMA(c, scale, lm, c);
9953                                                 if (surface->lightmapinfo->styles[2] != 255)
9954                                                 {
9955                                                         lm += size3;
9956                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9957                                                         VectorMA(c, scale, lm, c);
9958                                                         if (surface->lightmapinfo->styles[3] != 255)
9959                                                         {
9960                                                                 lm += size3;
9961                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9962                                                                 VectorMA(c, scale, lm, c);
9963                                                         }
9964                                                 }
9965                                         }
9966                                         c[0] >>= 7;
9967                                         c[1] >>= 7;
9968                                         c[2] >>= 7;
9969                                         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);
9970                                         numvertices++;
9971                                 }
9972                         }
9973                         else
9974                         {
9975                                 for (j = 0;j < surfacenumvertices;j++)
9976                                 {
9977                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9978                                         numvertices++;
9979                                 }
9980                         }
9981                 }
9982         }
9983
9984         // if vertices are deformed (sprite flares and things in maps, possibly
9985         // water waves, bulges and other deformations), modify the copied vertices
9986         // in place
9987         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9988         {
9989                 float scale;
9990                 switch (deform->deform)
9991                 {
9992                 default:
9993                 case Q3DEFORM_PROJECTIONSHADOW:
9994                 case Q3DEFORM_TEXT0:
9995                 case Q3DEFORM_TEXT1:
9996                 case Q3DEFORM_TEXT2:
9997                 case Q3DEFORM_TEXT3:
9998                 case Q3DEFORM_TEXT4:
9999                 case Q3DEFORM_TEXT5:
10000                 case Q3DEFORM_TEXT6:
10001                 case Q3DEFORM_TEXT7:
10002                 case Q3DEFORM_NONE:
10003                         break;
10004                 case Q3DEFORM_AUTOSPRITE:
10005                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10006                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10007                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10008                         VectorNormalize(newforward);
10009                         VectorNormalize(newright);
10010                         VectorNormalize(newup);
10011 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10012 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10013 //                      rsurface.batchvertex3f_bufferoffset = 0;
10014 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10015 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
10016 //                      rsurface.batchsvector3f_bufferoffset = 0;
10017 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10018 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
10019 //                      rsurface.batchtvector3f_bufferoffset = 0;
10020 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10021 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10022 //                      rsurface.batchnormal3f_bufferoffset = 0;
10023                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10024                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10025                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10026                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10027                                 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);
10028                         // a single autosprite surface can contain multiple sprites...
10029                         for (j = 0;j < batchnumvertices - 3;j += 4)
10030                         {
10031                                 VectorClear(center);
10032                                 for (i = 0;i < 4;i++)
10033                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10034                                 VectorScale(center, 0.25f, center);
10035                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10036                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10037                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10038                                 for (i = 0;i < 4;i++)
10039                                 {
10040                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10041                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10042                                 }
10043                         }
10044                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10045                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10046                         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);
10047                         break;
10048                 case Q3DEFORM_AUTOSPRITE2:
10049                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10050                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10051                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10052                         VectorNormalize(newforward);
10053                         VectorNormalize(newright);
10054                         VectorNormalize(newup);
10055 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10056 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10057 //                      rsurface.batchvertex3f_bufferoffset = 0;
10058                         {
10059                                 const float *v1, *v2;
10060                                 vec3_t start, end;
10061                                 float f, l;
10062                                 struct
10063                                 {
10064                                         float length2;
10065                                         const float *v1;
10066                                         const float *v2;
10067                                 }
10068                                 shortest[2];
10069                                 memset(shortest, 0, sizeof(shortest));
10070                                 // a single autosprite surface can contain multiple sprites...
10071                                 for (j = 0;j < batchnumvertices - 3;j += 4)
10072                                 {
10073                                         VectorClear(center);
10074                                         for (i = 0;i < 4;i++)
10075                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10076                                         VectorScale(center, 0.25f, center);
10077                                         // find the two shortest edges, then use them to define the
10078                                         // axis vectors for rotating around the central axis
10079                                         for (i = 0;i < 6;i++)
10080                                         {
10081                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10082                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10083                                                 l = VectorDistance2(v1, v2);
10084                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10085                                                 if (v1[2] != v2[2])
10086                                                         l += (1.0f / 1024.0f);
10087                                                 if (shortest[0].length2 > l || i == 0)
10088                                                 {
10089                                                         shortest[1] = shortest[0];
10090                                                         shortest[0].length2 = l;
10091                                                         shortest[0].v1 = v1;
10092                                                         shortest[0].v2 = v2;
10093                                                 }
10094                                                 else if (shortest[1].length2 > l || i == 1)
10095                                                 {
10096                                                         shortest[1].length2 = l;
10097                                                         shortest[1].v1 = v1;
10098                                                         shortest[1].v2 = v2;
10099                                                 }
10100                                         }
10101                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10102                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10103                                         // this calculates the right vector from the shortest edge
10104                                         // and the up vector from the edge midpoints
10105                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10106                                         VectorNormalize(right);
10107                                         VectorSubtract(end, start, up);
10108                                         VectorNormalize(up);
10109                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10110                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10111                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10112                                         VectorNegate(forward, forward);
10113                                         VectorReflect(forward, 0, up, forward);
10114                                         VectorNormalize(forward);
10115                                         CrossProduct(up, forward, newright);
10116                                         VectorNormalize(newright);
10117                                         // rotate the quad around the up axis vector, this is made
10118                                         // especially easy by the fact we know the quad is flat,
10119                                         // so we only have to subtract the center position and
10120                                         // measure distance along the right vector, and then
10121                                         // multiply that by the newright vector and add back the
10122                                         // center position
10123                                         // we also need to subtract the old position to undo the
10124                                         // displacement from the center, which we do with a
10125                                         // DotProduct, the subtraction/addition of center is also
10126                                         // optimized into DotProducts here
10127                                         l = DotProduct(right, center);
10128                                         for (i = 0;i < 4;i++)
10129                                         {
10130                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10131                                                 f = DotProduct(right, v1) - l;
10132                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10133                                         }
10134                                 }
10135                         }
10136                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10137                         {
10138 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10139 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10140 //                              rsurface.batchnormal3f_bufferoffset = 0;
10141                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10142                         }
10143                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10144                         {
10145 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10146 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10147 //                              rsurface.batchsvector3f_bufferoffset = 0;
10148 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10149 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10150 //                              rsurface.batchtvector3f_bufferoffset = 0;
10151                                 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);
10152                         }
10153                         break;
10154                 case Q3DEFORM_NORMAL:
10155                         // deform the normals to make reflections wavey
10156                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10157                         rsurface.batchnormal3f_vertexbuffer = NULL;
10158                         rsurface.batchnormal3f_bufferoffset = 0;
10159                         for (j = 0;j < batchnumvertices;j++)
10160                         {
10161                                 float vertex[3];
10162                                 float *normal = rsurface.batchnormal3f + 3*j;
10163                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10164                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10165                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10166                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10167                                 VectorNormalize(normal);
10168                         }
10169                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10170                         {
10171 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10172 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10173 //                              rsurface.batchsvector3f_bufferoffset = 0;
10174 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10175 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10176 //                              rsurface.batchtvector3f_bufferoffset = 0;
10177                                 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);
10178                         }
10179                         break;
10180                 case Q3DEFORM_WAVE:
10181                         // deform vertex array to make wavey water and flags and such
10182                         waveparms[0] = deform->waveparms[0];
10183                         waveparms[1] = deform->waveparms[1];
10184                         waveparms[2] = deform->waveparms[2];
10185                         waveparms[3] = deform->waveparms[3];
10186                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10187                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10188                         // this is how a divisor of vertex influence on deformation
10189                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10190                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10191 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10192 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10193 //                      rsurface.batchvertex3f_bufferoffset = 0;
10194 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10195 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10196 //                      rsurface.batchnormal3f_bufferoffset = 0;
10197                         for (j = 0;j < batchnumvertices;j++)
10198                         {
10199                                 // if the wavefunc depends on time, evaluate it per-vertex
10200                                 if (waveparms[3])
10201                                 {
10202                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10203                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10204                                 }
10205                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10206                         }
10207                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10208                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10209                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10210                         {
10211 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10212 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10213 //                              rsurface.batchsvector3f_bufferoffset = 0;
10214 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10215 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10216 //                              rsurface.batchtvector3f_bufferoffset = 0;
10217                                 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);
10218                         }
10219                         break;
10220                 case Q3DEFORM_BULGE:
10221                         // deform vertex array to make the surface have moving bulges
10222 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10223 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10224 //                      rsurface.batchvertex3f_bufferoffset = 0;
10225 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10226 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10227 //                      rsurface.batchnormal3f_bufferoffset = 0;
10228                         for (j = 0;j < batchnumvertices;j++)
10229                         {
10230                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10231                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10232                         }
10233                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10234                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10235                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10236                         {
10237 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10238 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10239 //                              rsurface.batchsvector3f_bufferoffset = 0;
10240 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10241 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10242 //                              rsurface.batchtvector3f_bufferoffset = 0;
10243                                 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);
10244                         }
10245                         break;
10246                 case Q3DEFORM_MOVE:
10247                         // deform vertex array
10248                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10249                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10250                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10251                         VectorScale(deform->parms, scale, waveparms);
10252 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10253 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10254 //                      rsurface.batchvertex3f_bufferoffset = 0;
10255                         for (j = 0;j < batchnumvertices;j++)
10256                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10257                         break;
10258                 }
10259         }
10260
10261         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10262         {
10263         // generate texcoords based on the chosen texcoord source
10264                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10265                 {
10266                 default:
10267                 case Q3TCGEN_TEXTURE:
10268                         break;
10269                 case Q3TCGEN_LIGHTMAP:
10270         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10271         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10272         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10273                         if (rsurface.batchtexcoordlightmap2f)
10274                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10275                         break;
10276                 case Q3TCGEN_VECTOR:
10277         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10278         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10279         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10280                         for (j = 0;j < batchnumvertices;j++)
10281                         {
10282                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10283                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10284                         }
10285                         break;
10286                 case Q3TCGEN_ENVIRONMENT:
10287                         // make environment reflections using a spheremap
10288                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10289                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10290                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10291                         for (j = 0;j < batchnumvertices;j++)
10292                         {
10293                                 // identical to Q3A's method, but executed in worldspace so
10294                                 // carried models can be shiny too
10295
10296                                 float viewer[3], d, reflected[3], worldreflected[3];
10297
10298                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10299                                 // VectorNormalize(viewer);
10300
10301                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10302
10303                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10304                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10305                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10306                                 // note: this is proportinal to viewer, so we can normalize later
10307
10308                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10309                                 VectorNormalize(worldreflected);
10310
10311                                 // note: this sphere map only uses world x and z!
10312                                 // so positive and negative y will LOOK THE SAME.
10313                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10314                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10315                         }
10316                         break;
10317                 }
10318                 // the only tcmod that needs software vertex processing is turbulent, so
10319                 // check for it here and apply the changes if needed
10320                 // and we only support that as the first one
10321                 // (handling a mixture of turbulent and other tcmods would be problematic
10322                 //  without punting it entirely to a software path)
10323                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10324                 {
10325                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10326                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10327         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10328         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10329         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10330                         for (j = 0;j < batchnumvertices;j++)
10331                         {
10332                                 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);
10333                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10334                         }
10335                 }
10336         }
10337
10338         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10339         {
10340                 // convert the modified arrays to vertex structs
10341 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10342 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10343 //              rsurface.batchvertexmesh_bufferoffset = 0;
10344                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10345                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10346                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10347                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10348                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10349                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10350                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10351                 {
10352                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10353                         {
10354                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10355                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10356                         }
10357                 }
10358                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10359                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10360                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10361                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10362                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10363                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10364                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10365                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10366                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10367                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10368                 {
10369                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10370                         {
10371                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10372                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10373                         }
10374                 }
10375         }
10376
10377         // upload buffer data for the dynamic batch
10378         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10379         {
10380                 if (rsurface.batchvertexmesh)
10381                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10382                 else
10383                 {
10384                         if (rsurface.batchvertex3f)
10385                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10386                         if (rsurface.batchsvector3f)
10387                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10388                         if (rsurface.batchtvector3f)
10389                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10390                         if (rsurface.batchnormal3f)
10391                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10392                         if (rsurface.batchlightmapcolor4f)
10393                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10394                         if (rsurface.batchtexcoordtexture2f)
10395                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10396                         if (rsurface.batchtexcoordlightmap2f)
10397                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10398                         if (rsurface.batchskeletalindex4ub)
10399                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10400                         if (rsurface.batchskeletalweight4ub)
10401                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10402                 }
10403                 if (rsurface.batchelement3s)
10404                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10405                 else if (rsurface.batchelement3i)
10406                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10407         }
10408 }
10409
10410 void RSurf_DrawBatch(void)
10411 {
10412         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10413         // through the pipeline, killing it earlier in the pipeline would have
10414         // per-surface overhead rather than per-batch overhead, so it's best to
10415         // reject it here, before it hits glDraw.
10416         if (rsurface.batchnumtriangles == 0)
10417                 return;
10418 #if 0
10419         // batch debugging code
10420         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10421         {
10422                 int i;
10423                 int j;
10424                 int c;
10425                 const int *e;
10426                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10427                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10428                 {
10429                         c = e[i];
10430                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10431                         {
10432                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10433                                 {
10434                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10435                                                 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);
10436                                         break;
10437                                 }
10438                         }
10439                 }
10440         }
10441 #endif
10442         if (rsurface.batchmultidraw)
10443         {
10444                 // issue multiple draws rather than copying index data
10445                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10446                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10447                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10448                 for (i = 0;i < numsurfaces;)
10449                 {
10450                         // combine consecutive surfaces as one draw
10451                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10452                                 if (surfacelist[j] != surfacelist[k] + 1)
10453                                         break;
10454                         firstvertex = surfacelist[i]->num_firstvertex;
10455                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10456                         firsttriangle = surfacelist[i]->num_firsttriangle;
10457                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10458                         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);
10459                         i = j;
10460                 }
10461         }
10462         else
10463         {
10464                 // there is only one consecutive run of index data (may have been combined)
10465                 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);
10466         }
10467 }
10468
10469 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10470 {
10471         // pick the closest matching water plane
10472         int planeindex, vertexindex, bestplaneindex = -1;
10473         float d, bestd;
10474         vec3_t vert;
10475         const float *v;
10476         r_waterstate_waterplane_t *p;
10477         qboolean prepared = false;
10478         bestd = 0;
10479         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10480         {
10481                 if(p->camera_entity != rsurface.texture->camera_entity)
10482                         continue;
10483                 d = 0;
10484                 if(!prepared)
10485                 {
10486                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10487                         prepared = true;
10488                         if(rsurface.batchnumvertices == 0)
10489                                 break;
10490                 }
10491                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10492                 {
10493                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10494                         d += fabs(PlaneDiff(vert, &p->plane));
10495                 }
10496                 if (bestd > d || bestplaneindex < 0)
10497                 {
10498                         bestd = d;
10499                         bestplaneindex = planeindex;
10500                 }
10501         }
10502         return bestplaneindex;
10503         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10504         // this situation though, as it might be better to render single larger
10505         // batches with useless stuff (backface culled for example) than to
10506         // render multiple smaller batches
10507 }
10508
10509 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10510 {
10511         int i;
10512         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10513         rsurface.passcolor4f_vertexbuffer = 0;
10514         rsurface.passcolor4f_bufferoffset = 0;
10515         for (i = 0;i < rsurface.batchnumvertices;i++)
10516                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10517 }
10518
10519 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10520 {
10521         int i;
10522         float f;
10523         const float *v;
10524         const float *c;
10525         float *c2;
10526         if (rsurface.passcolor4f)
10527         {
10528                 // generate color arrays
10529                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10530                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10531                 rsurface.passcolor4f_vertexbuffer = 0;
10532                 rsurface.passcolor4f_bufferoffset = 0;
10533                 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)
10534                 {
10535                         f = RSurf_FogVertex(v);
10536                         c2[0] = c[0] * f;
10537                         c2[1] = c[1] * f;
10538                         c2[2] = c[2] * f;
10539                         c2[3] = c[3];
10540                 }
10541         }
10542         else
10543         {
10544                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10545                 rsurface.passcolor4f_vertexbuffer = 0;
10546                 rsurface.passcolor4f_bufferoffset = 0;
10547                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10548                 {
10549                         f = RSurf_FogVertex(v);
10550                         c2[0] = f;
10551                         c2[1] = f;
10552                         c2[2] = f;
10553                         c2[3] = 1;
10554                 }
10555         }
10556 }
10557
10558 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10559 {
10560         int i;
10561         float f;
10562         const float *v;
10563         const float *c;
10564         float *c2;
10565         if (!rsurface.passcolor4f)
10566                 return;
10567         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10568         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10569         rsurface.passcolor4f_vertexbuffer = 0;
10570         rsurface.passcolor4f_bufferoffset = 0;
10571         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)
10572         {
10573                 f = RSurf_FogVertex(v);
10574                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10575                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10576                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10577                 c2[3] = c[3];
10578         }
10579 }
10580
10581 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10582 {
10583         int i;
10584         const float *c;
10585         float *c2;
10586         if (!rsurface.passcolor4f)
10587                 return;
10588         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10589         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10590         rsurface.passcolor4f_vertexbuffer = 0;
10591         rsurface.passcolor4f_bufferoffset = 0;
10592         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10593         {
10594                 c2[0] = c[0] * r;
10595                 c2[1] = c[1] * g;
10596                 c2[2] = c[2] * b;
10597                 c2[3] = c[3] * a;
10598         }
10599 }
10600
10601 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10602 {
10603         int i;
10604         const float *c;
10605         float *c2;
10606         if (!rsurface.passcolor4f)
10607                 return;
10608         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10609         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10610         rsurface.passcolor4f_vertexbuffer = 0;
10611         rsurface.passcolor4f_bufferoffset = 0;
10612         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10613         {
10614                 c2[0] = c[0] + r_refdef.scene.ambient;
10615                 c2[1] = c[1] + r_refdef.scene.ambient;
10616                 c2[2] = c[2] + r_refdef.scene.ambient;
10617                 c2[3] = c[3];
10618         }
10619 }
10620
10621 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10622 {
10623         // TODO: optimize
10624         rsurface.passcolor4f = NULL;
10625         rsurface.passcolor4f_vertexbuffer = 0;
10626         rsurface.passcolor4f_bufferoffset = 0;
10627         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10628         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10629         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10630         GL_Color(r, g, b, a);
10631         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10632         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10633         R_Mesh_TexMatrix(0, NULL);
10634         RSurf_DrawBatch();
10635 }
10636
10637 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10638 {
10639         // TODO: optimize applyfog && applycolor case
10640         // just apply fog if necessary, and tint the fog color array if necessary
10641         rsurface.passcolor4f = NULL;
10642         rsurface.passcolor4f_vertexbuffer = 0;
10643         rsurface.passcolor4f_bufferoffset = 0;
10644         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10645         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10646         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10647         GL_Color(r, g, b, a);
10648         RSurf_DrawBatch();
10649 }
10650
10651 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10652 {
10653         // TODO: optimize
10654         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10655         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10656         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10657         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10658         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10659         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10660         GL_Color(r, g, b, a);
10661         RSurf_DrawBatch();
10662 }
10663
10664 static void RSurf_DrawBatch_GL11_ClampColor(void)
10665 {
10666         int i;
10667         const float *c1;
10668         float *c2;
10669         if (!rsurface.passcolor4f)
10670                 return;
10671         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10672         {
10673                 c2[0] = bound(0.0f, c1[0], 1.0f);
10674                 c2[1] = bound(0.0f, c1[1], 1.0f);
10675                 c2[2] = bound(0.0f, c1[2], 1.0f);
10676                 c2[3] = bound(0.0f, c1[3], 1.0f);
10677         }
10678 }
10679
10680 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10681 {
10682         int i;
10683         float f;
10684         const float *v;
10685         const float *n;
10686         float *c;
10687         //vec3_t eyedir;
10688
10689         // fake shading
10690         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10691         rsurface.passcolor4f_vertexbuffer = 0;
10692         rsurface.passcolor4f_bufferoffset = 0;
10693         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)
10694         {
10695                 f = -DotProduct(r_refdef.view.forward, n);
10696                 f = max(0, f);
10697                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10698                 f *= r_refdef.lightmapintensity;
10699                 Vector4Set(c, f, f, f, 1);
10700         }
10701 }
10702
10703 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10704 {
10705         RSurf_DrawBatch_GL11_ApplyFakeLight();
10706         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10707         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10708         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10709         GL_Color(r, g, b, a);
10710         RSurf_DrawBatch();
10711 }
10712
10713 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10714 {
10715         int i;
10716         float f;
10717         float alpha;
10718         const float *v;
10719         const float *n;
10720         float *c;
10721         vec3_t ambientcolor;
10722         vec3_t diffusecolor;
10723         vec3_t lightdir;
10724         // TODO: optimize
10725         // model lighting
10726         VectorCopy(rsurface.modellight_lightdir, lightdir);
10727         f = 0.5f * r_refdef.lightmapintensity;
10728         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10729         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10730         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10731         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10732         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10733         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10734         alpha = *a;
10735         if (VectorLength2(diffusecolor) > 0)
10736         {
10737                 // q3-style directional shading
10738                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10739                 rsurface.passcolor4f_vertexbuffer = 0;
10740                 rsurface.passcolor4f_bufferoffset = 0;
10741                 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)
10742                 {
10743                         if ((f = DotProduct(n, lightdir)) > 0)
10744                                 VectorMA(ambientcolor, f, diffusecolor, c);
10745                         else
10746                                 VectorCopy(ambientcolor, c);
10747                         c[3] = alpha;
10748                 }
10749                 *r = 1;
10750                 *g = 1;
10751                 *b = 1;
10752                 *a = 1;
10753                 *applycolor = false;
10754         }
10755         else
10756         {
10757                 *r = ambientcolor[0];
10758                 *g = ambientcolor[1];
10759                 *b = ambientcolor[2];
10760                 rsurface.passcolor4f = NULL;
10761                 rsurface.passcolor4f_vertexbuffer = 0;
10762                 rsurface.passcolor4f_bufferoffset = 0;
10763         }
10764 }
10765
10766 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10767 {
10768         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10769         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10770         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10771         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10772         GL_Color(r, g, b, a);
10773         RSurf_DrawBatch();
10774 }
10775
10776 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10777 {
10778         int i;
10779         float f;
10780         const float *v;
10781         float *c;
10782
10783         // fake shading
10784         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10785         rsurface.passcolor4f_vertexbuffer = 0;
10786         rsurface.passcolor4f_bufferoffset = 0;
10787
10788         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10789         {
10790                 f = 1 - RSurf_FogVertex(v);
10791                 c[0] = r;
10792                 c[1] = g;
10793                 c[2] = b;
10794                 c[3] = f * a;
10795         }
10796 }
10797
10798 void RSurf_SetupDepthAndCulling(void)
10799 {
10800         // submodels are biased to avoid z-fighting with world surfaces that they
10801         // may be exactly overlapping (avoids z-fighting artifacts on certain
10802         // doors and things in Quake maps)
10803         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10804         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10805         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10806         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10807 }
10808
10809 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10810 {
10811         // transparent sky would be ridiculous
10812         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10813                 return;
10814         R_SetupShader_Generic_NoTexture(false, false);
10815         skyrenderlater = true;
10816         RSurf_SetupDepthAndCulling();
10817         GL_DepthMask(true);
10818         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10819         // skymasking on them, and Quake3 never did sky masking (unlike
10820         // software Quake and software Quake2), so disable the sky masking
10821         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10822         // and skymasking also looks very bad when noclipping outside the
10823         // level, so don't use it then either.
10824         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10825         {
10826                 R_Mesh_ResetTextureState();
10827                 if (skyrendermasked)
10828                 {
10829                         R_SetupShader_DepthOrShadow(false, false, false);
10830                         // depth-only (masking)
10831                         GL_ColorMask(0,0,0,0);
10832                         // just to make sure that braindead drivers don't draw
10833                         // anything despite that colormask...
10834                         GL_BlendFunc(GL_ZERO, GL_ONE);
10835                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10836                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10837                 }
10838                 else
10839                 {
10840                         R_SetupShader_Generic_NoTexture(false, false);
10841                         // fog sky
10842                         GL_BlendFunc(GL_ONE, GL_ZERO);
10843                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10844                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10845                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10846                 }
10847                 RSurf_DrawBatch();
10848                 if (skyrendermasked)
10849                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10850         }
10851         R_Mesh_ResetTextureState();
10852         GL_Color(1, 1, 1, 1);
10853 }
10854
10855 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10856 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10857 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10858 {
10859         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10860                 return;
10861         if (prepass)
10862         {
10863                 // render screenspace normalmap to texture
10864                 GL_DepthMask(true);
10865                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10866                 RSurf_DrawBatch();
10867                 return;
10868         }
10869
10870         // bind lightmap texture
10871
10872         // water/refraction/reflection/camera surfaces have to be handled specially
10873         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10874         {
10875                 int start, end, startplaneindex;
10876                 for (start = 0;start < texturenumsurfaces;start = end)
10877                 {
10878                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10879                         if(startplaneindex < 0)
10880                         {
10881                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10882                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10883                                 end = start + 1;
10884                                 continue;
10885                         }
10886                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10887                                 ;
10888                         // now that we have a batch using the same planeindex, render it
10889                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10890                         {
10891                                 // render water or distortion background
10892                                 GL_DepthMask(true);
10893                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10894                                 RSurf_DrawBatch();
10895                                 // blend surface on top
10896                                 GL_DepthMask(false);
10897                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10898                                 RSurf_DrawBatch();
10899                         }
10900                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10901                         {
10902                                 // render surface with reflection texture as input
10903                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10904                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10905                                 RSurf_DrawBatch();
10906                         }
10907                 }
10908                 return;
10909         }
10910
10911         // render surface batch normally
10912         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10913         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10914         RSurf_DrawBatch();
10915 }
10916
10917 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10918 {
10919         // OpenGL 1.3 path - anything not completely ancient
10920         qboolean applycolor;
10921         qboolean applyfog;
10922         int layerindex;
10923         const texturelayer_t *layer;
10924         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10925         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10926
10927         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10928         {
10929                 vec4_t layercolor;
10930                 int layertexrgbscale;
10931                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10932                 {
10933                         if (layerindex == 0)
10934                                 GL_AlphaTest(true);
10935                         else
10936                         {
10937                                 GL_AlphaTest(false);
10938                                 GL_DepthFunc(GL_EQUAL);
10939                         }
10940                 }
10941                 GL_DepthMask(layer->depthmask && writedepth);
10942                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10943                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10944                 {
10945                         layertexrgbscale = 4;
10946                         VectorScale(layer->color, 0.25f, layercolor);
10947                 }
10948                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10949                 {
10950                         layertexrgbscale = 2;
10951                         VectorScale(layer->color, 0.5f, layercolor);
10952                 }
10953                 else
10954                 {
10955                         layertexrgbscale = 1;
10956                         VectorScale(layer->color, 1.0f, layercolor);
10957                 }
10958                 layercolor[3] = layer->color[3];
10959                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10960                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10961                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10962                 switch (layer->type)
10963                 {
10964                 case TEXTURELAYERTYPE_LITTEXTURE:
10965                         // single-pass lightmapped texture with 2x rgbscale
10966                         R_Mesh_TexBind(0, r_texture_white);
10967                         R_Mesh_TexMatrix(0, NULL);
10968                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10969                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10970                         R_Mesh_TexBind(1, layer->texture);
10971                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10972                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10973                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10974                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10975                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10976                         else if (FAKELIGHT_ENABLED)
10977                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10978                         else if (rsurface.uselightmaptexture)
10979                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10980                         else
10981                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10982                         break;
10983                 case TEXTURELAYERTYPE_TEXTURE:
10984                         // singletexture unlit texture with transparency support
10985                         R_Mesh_TexBind(0, layer->texture);
10986                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10987                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10988                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10989                         R_Mesh_TexBind(1, 0);
10990                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10991                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10992                         break;
10993                 case TEXTURELAYERTYPE_FOG:
10994                         // singletexture fogging
10995                         if (layer->texture)
10996                         {
10997                                 R_Mesh_TexBind(0, layer->texture);
10998                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10999                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11000                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11001                         }
11002                         else
11003                         {
11004                                 R_Mesh_TexBind(0, 0);
11005                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11006                         }
11007                         R_Mesh_TexBind(1, 0);
11008                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11009                         // generate a color array for the fog pass
11010                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11011                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11012                         RSurf_DrawBatch();
11013                         break;
11014                 default:
11015                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11016                 }
11017         }
11018         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11019         {
11020                 GL_DepthFunc(GL_LEQUAL);
11021                 GL_AlphaTest(false);
11022         }
11023 }
11024
11025 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11026 {
11027         // OpenGL 1.1 - crusty old voodoo path
11028         qboolean applyfog;
11029         int layerindex;
11030         const texturelayer_t *layer;
11031         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11032         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11033
11034         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11035         {
11036                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11037                 {
11038                         if (layerindex == 0)
11039                                 GL_AlphaTest(true);
11040                         else
11041                         {
11042                                 GL_AlphaTest(false);
11043                                 GL_DepthFunc(GL_EQUAL);
11044                         }
11045                 }
11046                 GL_DepthMask(layer->depthmask && writedepth);
11047                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11048                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11049                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11050                 switch (layer->type)
11051                 {
11052                 case TEXTURELAYERTYPE_LITTEXTURE:
11053                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11054                         {
11055                                 // two-pass lit texture with 2x rgbscale
11056                                 // first the lightmap pass
11057                                 R_Mesh_TexBind(0, r_texture_white);
11058                                 R_Mesh_TexMatrix(0, NULL);
11059                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11060                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11061                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11062                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11063                                 else if (FAKELIGHT_ENABLED)
11064                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11065                                 else if (rsurface.uselightmaptexture)
11066                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11067                                 else
11068                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11069                                 // then apply the texture to it
11070                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11071                                 R_Mesh_TexBind(0, layer->texture);
11072                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11073                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11074                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11075                                 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);
11076                         }
11077                         else
11078                         {
11079                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11080                                 R_Mesh_TexBind(0, layer->texture);
11081                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11082                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11083                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11084                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11085                                         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);
11086                                 else if (FAKELIGHT_ENABLED)
11087                                         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);
11088                                 else
11089                                         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);
11090                         }
11091                         break;
11092                 case TEXTURELAYERTYPE_TEXTURE:
11093                         // singletexture unlit texture with transparency support
11094                         R_Mesh_TexBind(0, layer->texture);
11095                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11096                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11097                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11098                         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);
11099                         break;
11100                 case TEXTURELAYERTYPE_FOG:
11101                         // singletexture fogging
11102                         if (layer->texture)
11103                         {
11104                                 R_Mesh_TexBind(0, layer->texture);
11105                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11106                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11107                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11108                         }
11109                         else
11110                         {
11111                                 R_Mesh_TexBind(0, 0);
11112                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11113                         }
11114                         // generate a color array for the fog pass
11115                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11116                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11117                         RSurf_DrawBatch();
11118                         break;
11119                 default:
11120                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11121                 }
11122         }
11123         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11124         {
11125                 GL_DepthFunc(GL_LEQUAL);
11126                 GL_AlphaTest(false);
11127         }
11128 }
11129
11130 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11131 {
11132         int vi;
11133         int j;
11134         r_vertexgeneric_t *batchvertex;
11135         float c[4];
11136
11137 //      R_Mesh_ResetTextureState();
11138         R_SetupShader_Generic_NoTexture(false, false);
11139
11140         if(rsurface.texture && rsurface.texture->currentskinframe)
11141         {
11142                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11143                 c[3] *= rsurface.texture->currentalpha;
11144         }
11145         else
11146         {
11147                 c[0] = 1;
11148                 c[1] = 0;
11149                 c[2] = 1;
11150                 c[3] = 1;
11151         }
11152
11153         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11154         {
11155                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11156                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11157                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11158         }
11159
11160         // brighten it up (as texture value 127 means "unlit")
11161         c[0] *= 2 * r_refdef.view.colorscale;
11162         c[1] *= 2 * r_refdef.view.colorscale;
11163         c[2] *= 2 * r_refdef.view.colorscale;
11164
11165         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11166                 c[3] *= r_wateralpha.value;
11167
11168         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11169         {
11170                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11171                 GL_DepthMask(false);
11172         }
11173         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11174         {
11175                 GL_BlendFunc(GL_ONE, GL_ONE);
11176                 GL_DepthMask(false);
11177         }
11178         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11179         {
11180                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11181                 GL_DepthMask(false);
11182         }
11183         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11184         {
11185                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11186                 GL_DepthMask(false);
11187         }
11188         else
11189         {
11190                 GL_BlendFunc(GL_ONE, GL_ZERO);
11191                 GL_DepthMask(writedepth);
11192         }
11193
11194         if (r_showsurfaces.integer == 3)
11195         {
11196                 rsurface.passcolor4f = NULL;
11197
11198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11199                 {
11200                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11201
11202                         rsurface.passcolor4f = NULL;
11203                         rsurface.passcolor4f_vertexbuffer = 0;
11204                         rsurface.passcolor4f_bufferoffset = 0;
11205                 }
11206                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11207                 {
11208                         qboolean applycolor = true;
11209                         float one = 1.0;
11210
11211                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11212
11213                         r_refdef.lightmapintensity = 1;
11214                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11215                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11216                 }
11217                 else if (FAKELIGHT_ENABLED)
11218                 {
11219                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11220
11221                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11222                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11223                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11224                 }
11225                 else
11226                 {
11227                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11228
11229                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11230                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11231                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11232                 }
11233
11234                 if(!rsurface.passcolor4f)
11235                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11236
11237                 RSurf_DrawBatch_GL11_ApplyAmbient();
11238                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11239                 if(r_refdef.fogenabled)
11240                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11241                 RSurf_DrawBatch_GL11_ClampColor();
11242
11243                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11244                 R_SetupShader_Generic_NoTexture(false, false);
11245                 RSurf_DrawBatch();
11246         }
11247         else if (!r_refdef.view.showdebug)
11248         {
11249                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11250                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11251                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11252                 {
11253                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11254                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11255                 }
11256                 R_Mesh_PrepareVertices_Generic_Unlock();
11257                 RSurf_DrawBatch();
11258         }
11259         else if (r_showsurfaces.integer == 4)
11260         {
11261                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11262                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11263                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11264                 {
11265                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11266                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11267                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11268                 }
11269                 R_Mesh_PrepareVertices_Generic_Unlock();
11270                 RSurf_DrawBatch();
11271         }
11272         else if (r_showsurfaces.integer == 2)
11273         {
11274                 const int *e;
11275                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11276                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11277                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11278                 {
11279                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11280                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11281                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11282                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11283                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11284                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11285                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11286                 }
11287                 R_Mesh_PrepareVertices_Generic_Unlock();
11288                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11289         }
11290         else
11291         {
11292                 int texturesurfaceindex;
11293                 int k;
11294                 const msurface_t *surface;
11295                 float surfacecolor4f[4];
11296                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11297                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11298                 vi = 0;
11299                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11300                 {
11301                         surface = texturesurfacelist[texturesurfaceindex];
11302                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11303                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11304                         for (j = 0;j < surface->num_vertices;j++)
11305                         {
11306                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11307                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11308                                 vi++;
11309                         }
11310                 }
11311                 R_Mesh_PrepareVertices_Generic_Unlock();
11312                 RSurf_DrawBatch();
11313         }
11314 }
11315
11316 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11317 {
11318         CHECKGLERROR
11319         RSurf_SetupDepthAndCulling();
11320         if (r_showsurfaces.integer)
11321         {
11322                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11323                 return;
11324         }
11325         switch (vid.renderpath)
11326         {
11327         case RENDERPATH_GL20:
11328         case RENDERPATH_D3D9:
11329         case RENDERPATH_D3D10:
11330         case RENDERPATH_D3D11:
11331         case RENDERPATH_SOFT:
11332         case RENDERPATH_GLES2:
11333                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11334                 break;
11335         case RENDERPATH_GL13:
11336         case RENDERPATH_GLES1:
11337                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11338                 break;
11339         case RENDERPATH_GL11:
11340                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11341                 break;
11342         }
11343         CHECKGLERROR
11344 }
11345
11346 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11347 {
11348         CHECKGLERROR
11349         RSurf_SetupDepthAndCulling();
11350         if (r_showsurfaces.integer)
11351         {
11352                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11353                 return;
11354         }
11355         switch (vid.renderpath)
11356         {
11357         case RENDERPATH_GL20:
11358         case RENDERPATH_D3D9:
11359         case RENDERPATH_D3D10:
11360         case RENDERPATH_D3D11:
11361         case RENDERPATH_SOFT:
11362         case RENDERPATH_GLES2:
11363                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11364                 break;
11365         case RENDERPATH_GL13:
11366         case RENDERPATH_GLES1:
11367                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11368                 break;
11369         case RENDERPATH_GL11:
11370                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11371                 break;
11372         }
11373         CHECKGLERROR
11374 }
11375
11376 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11377 {
11378         int i, j;
11379         int texturenumsurfaces, endsurface;
11380         texture_t *texture;
11381         const msurface_t *surface;
11382         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11383
11384         // if the model is static it doesn't matter what value we give for
11385         // wantnormals and wanttangents, so this logic uses only rules applicable
11386         // to a model, knowing that they are meaningless otherwise
11387         if (ent == r_refdef.scene.worldentity)
11388                 RSurf_ActiveWorldEntity();
11389         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11390                 RSurf_ActiveModelEntity(ent, false, false, false);
11391         else
11392         {
11393                 switch (vid.renderpath)
11394                 {
11395                 case RENDERPATH_GL20:
11396                 case RENDERPATH_D3D9:
11397                 case RENDERPATH_D3D10:
11398                 case RENDERPATH_D3D11:
11399                 case RENDERPATH_SOFT:
11400                 case RENDERPATH_GLES2:
11401                         RSurf_ActiveModelEntity(ent, true, true, false);
11402                         break;
11403                 case RENDERPATH_GL11:
11404                 case RENDERPATH_GL13:
11405                 case RENDERPATH_GLES1:
11406                         RSurf_ActiveModelEntity(ent, true, false, false);
11407                         break;
11408                 }
11409         }
11410
11411         if (r_transparentdepthmasking.integer)
11412         {
11413                 qboolean setup = false;
11414                 for (i = 0;i < numsurfaces;i = j)
11415                 {
11416                         j = i + 1;
11417                         surface = rsurface.modelsurfaces + surfacelist[i];
11418                         texture = surface->texture;
11419                         rsurface.texture = R_GetCurrentTexture(texture);
11420                         rsurface.lightmaptexture = NULL;
11421                         rsurface.deluxemaptexture = NULL;
11422                         rsurface.uselightmaptexture = false;
11423                         // scan ahead until we find a different texture
11424                         endsurface = min(i + 1024, numsurfaces);
11425                         texturenumsurfaces = 0;
11426                         texturesurfacelist[texturenumsurfaces++] = surface;
11427                         for (;j < endsurface;j++)
11428                         {
11429                                 surface = rsurface.modelsurfaces + surfacelist[j];
11430                                 if (texture != surface->texture)
11431                                         break;
11432                                 texturesurfacelist[texturenumsurfaces++] = surface;
11433                         }
11434                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11435                                 continue;
11436                         // render the range of surfaces as depth
11437                         if (!setup)
11438                         {
11439                                 setup = true;
11440                                 GL_ColorMask(0,0,0,0);
11441                                 GL_Color(1,1,1,1);
11442                                 GL_DepthTest(true);
11443                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11444                                 GL_DepthMask(true);
11445 //                              R_Mesh_ResetTextureState();
11446                         }
11447                         RSurf_SetupDepthAndCulling();
11448                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11449                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11450                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11451                         RSurf_DrawBatch();
11452                 }
11453                 if (setup)
11454                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11455         }
11456
11457         for (i = 0;i < numsurfaces;i = j)
11458         {
11459                 j = i + 1;
11460                 surface = rsurface.modelsurfaces + surfacelist[i];
11461                 texture = surface->texture;
11462                 rsurface.texture = R_GetCurrentTexture(texture);
11463                 // scan ahead until we find a different texture
11464                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11465                 texturenumsurfaces = 0;
11466                 texturesurfacelist[texturenumsurfaces++] = surface;
11467                 if(FAKELIGHT_ENABLED)
11468                 {
11469                         rsurface.lightmaptexture = NULL;
11470                         rsurface.deluxemaptexture = NULL;
11471                         rsurface.uselightmaptexture = false;
11472                         for (;j < endsurface;j++)
11473                         {
11474                                 surface = rsurface.modelsurfaces + surfacelist[j];
11475                                 if (texture != surface->texture)
11476                                         break;
11477                                 texturesurfacelist[texturenumsurfaces++] = surface;
11478                         }
11479                 }
11480                 else
11481                 {
11482                         rsurface.lightmaptexture = surface->lightmaptexture;
11483                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11484                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11485                         for (;j < endsurface;j++)
11486                         {
11487                                 surface = rsurface.modelsurfaces + surfacelist[j];
11488                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11489                                         break;
11490                                 texturesurfacelist[texturenumsurfaces++] = surface;
11491                         }
11492                 }
11493                 // render the range of surfaces
11494                 if (ent == r_refdef.scene.worldentity)
11495                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11496                 else
11497                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11498         }
11499         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11500 }
11501
11502 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11503 {
11504         // transparent surfaces get pushed off into the transparent queue
11505         int surfacelistindex;
11506         const msurface_t *surface;
11507         vec3_t tempcenter, center;
11508         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11509         {
11510                 surface = texturesurfacelist[surfacelistindex];
11511                 if (r_transparent_sortsurfacesbynearest.integer)
11512                 {
11513                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11514                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11515                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11516                 }
11517                 else
11518                 {
11519                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11520                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11521                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11522                 }
11523                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11524                 if (rsurface.entity->transparent_offset) // transparent offset
11525                 {
11526                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11527                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11528                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11529                 }
11530                 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);
11531         }
11532 }
11533
11534 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11535 {
11536         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11537                 return;
11538         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11539                 return;
11540         RSurf_SetupDepthAndCulling();
11541         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11542         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11543         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11544         RSurf_DrawBatch();
11545 }
11546
11547 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11548 {
11549         CHECKGLERROR
11550         if (depthonly)
11551                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11552         else if (prepass)
11553         {
11554                 if (!rsurface.texture->currentnumlayers)
11555                         return;
11556                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11557                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11558                 else
11559                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11560         }
11561         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11562                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11563         else if (!rsurface.texture->currentnumlayers)
11564                 return;
11565         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11566         {
11567                 // in the deferred case, transparent surfaces were queued during prepass
11568                 if (!r_shadow_usingdeferredprepass)
11569                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11570         }
11571         else
11572         {
11573                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11574                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11575         }
11576         CHECKGLERROR
11577 }
11578
11579 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11580 {
11581         int i, j;
11582         texture_t *texture;
11583         R_FrameData_SetMark();
11584         // break the surface list down into batches by texture and use of lightmapping
11585         for (i = 0;i < numsurfaces;i = j)
11586         {
11587                 j = i + 1;
11588                 // texture is the base texture pointer, rsurface.texture is the
11589                 // current frame/skin the texture is directing us to use (for example
11590                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11591                 // use skin 1 instead)
11592                 texture = surfacelist[i]->texture;
11593                 rsurface.texture = R_GetCurrentTexture(texture);
11594                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11595                 {
11596                         // if this texture is not the kind we want, skip ahead to the next one
11597                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11598                                 ;
11599                         continue;
11600                 }
11601                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11602                 {
11603                         rsurface.lightmaptexture = NULL;
11604                         rsurface.deluxemaptexture = NULL;
11605                         rsurface.uselightmaptexture = false;
11606                         // simply scan ahead until we find a different texture or lightmap state
11607                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11608                                 ;
11609                 }
11610                 else
11611                 {
11612                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11613                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11614                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11615                         // simply scan ahead until we find a different texture or lightmap state
11616                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11617                                 ;
11618                 }
11619                 // render the range of surfaces
11620                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11621         }
11622         R_FrameData_ReturnToMark();
11623 }
11624
11625 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11626 {
11627         CHECKGLERROR
11628         if (depthonly)
11629                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11630         else if (prepass)
11631         {
11632                 if (!rsurface.texture->currentnumlayers)
11633                         return;
11634                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11635                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11636                 else
11637                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11638         }
11639         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11640                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11641         else if (!rsurface.texture->currentnumlayers)
11642                 return;
11643         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11644         {
11645                 // in the deferred case, transparent surfaces were queued during prepass
11646                 if (!r_shadow_usingdeferredprepass)
11647                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11648         }
11649         else
11650         {
11651                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11652                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11653         }
11654         CHECKGLERROR
11655 }
11656
11657 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11658 {
11659         int i, j;
11660         texture_t *texture;
11661         R_FrameData_SetMark();
11662         // break the surface list down into batches by texture and use of lightmapping
11663         for (i = 0;i < numsurfaces;i = j)
11664         {
11665                 j = i + 1;
11666                 // texture is the base texture pointer, rsurface.texture is the
11667                 // current frame/skin the texture is directing us to use (for example
11668                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11669                 // use skin 1 instead)
11670                 texture = surfacelist[i]->texture;
11671                 rsurface.texture = R_GetCurrentTexture(texture);
11672                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11673                 {
11674                         // if this texture is not the kind we want, skip ahead to the next one
11675                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11676                                 ;
11677                         continue;
11678                 }
11679                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11680                 {
11681                         rsurface.lightmaptexture = NULL;
11682                         rsurface.deluxemaptexture = NULL;
11683                         rsurface.uselightmaptexture = false;
11684                         // simply scan ahead until we find a different texture or lightmap state
11685                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11686                                 ;
11687                 }
11688                 else
11689                 {
11690                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11691                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11692                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11693                         // simply scan ahead until we find a different texture or lightmap state
11694                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11695                                 ;
11696                 }
11697                 // render the range of surfaces
11698                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11699         }
11700         R_FrameData_ReturnToMark();
11701 }
11702
11703 float locboxvertex3f[6*4*3] =
11704 {
11705         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11706         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11707         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11708         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11709         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11710         1,0,0, 0,0,0, 0,1,0, 1,1,0
11711 };
11712
11713 unsigned short locboxelements[6*2*3] =
11714 {
11715          0, 1, 2, 0, 2, 3,
11716          4, 5, 6, 4, 6, 7,
11717          8, 9,10, 8,10,11,
11718         12,13,14, 12,14,15,
11719         16,17,18, 16,18,19,
11720         20,21,22, 20,22,23
11721 };
11722
11723 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11724 {
11725         int i, j;
11726         cl_locnode_t *loc = (cl_locnode_t *)ent;
11727         vec3_t mins, size;
11728         float vertex3f[6*4*3];
11729         CHECKGLERROR
11730         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11731         GL_DepthMask(false);
11732         GL_DepthRange(0, 1);
11733         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11734         GL_DepthTest(true);
11735         GL_CullFace(GL_NONE);
11736         R_EntityMatrix(&identitymatrix);
11737
11738 //      R_Mesh_ResetTextureState();
11739
11740         i = surfacelist[0];
11741         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11742                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11743                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11744                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11745
11746         if (VectorCompare(loc->mins, loc->maxs))
11747         {
11748                 VectorSet(size, 2, 2, 2);
11749                 VectorMA(loc->mins, -0.5f, size, mins);
11750         }
11751         else
11752         {
11753                 VectorCopy(loc->mins, mins);
11754                 VectorSubtract(loc->maxs, loc->mins, size);
11755         }
11756
11757         for (i = 0;i < 6*4*3;)
11758                 for (j = 0;j < 3;j++, i++)
11759                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11760
11761         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11762         R_SetupShader_Generic_NoTexture(false, false);
11763         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11764 }
11765
11766 void R_DrawLocs(void)
11767 {
11768         int index;
11769         cl_locnode_t *loc, *nearestloc;
11770         vec3_t center;
11771         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11772         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11773         {
11774                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11775                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11776         }
11777 }
11778
11779 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11780 {
11781         if (decalsystem->decals)
11782                 Mem_Free(decalsystem->decals);
11783         memset(decalsystem, 0, sizeof(*decalsystem));
11784 }
11785
11786 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)
11787 {
11788         tridecal_t *decal;
11789         tridecal_t *decals;
11790         int i;
11791
11792         // expand or initialize the system
11793         if (decalsystem->maxdecals <= decalsystem->numdecals)
11794         {
11795                 decalsystem_t old = *decalsystem;
11796                 qboolean useshortelements;
11797                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11798                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11799                 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)));
11800                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11801                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11802                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11803                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11804                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11805                 if (decalsystem->numdecals)
11806                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11807                 if (old.decals)
11808                         Mem_Free(old.decals);
11809                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11810                         decalsystem->element3i[i] = i;
11811                 if (useshortelements)
11812                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11813                                 decalsystem->element3s[i] = i;
11814         }
11815
11816         // grab a decal and search for another free slot for the next one
11817         decals = decalsystem->decals;
11818         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11819         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11820                 ;
11821         decalsystem->freedecal = i;
11822         if (decalsystem->numdecals <= i)
11823                 decalsystem->numdecals = i + 1;
11824
11825         // initialize the decal
11826         decal->lived = 0;
11827         decal->triangleindex = triangleindex;
11828         decal->surfaceindex = surfaceindex;
11829         decal->decalsequence = decalsequence;
11830         decal->color4f[0][0] = c0[0];
11831         decal->color4f[0][1] = c0[1];
11832         decal->color4f[0][2] = c0[2];
11833         decal->color4f[0][3] = 1;
11834         decal->color4f[1][0] = c1[0];
11835         decal->color4f[1][1] = c1[1];
11836         decal->color4f[1][2] = c1[2];
11837         decal->color4f[1][3] = 1;
11838         decal->color4f[2][0] = c2[0];
11839         decal->color4f[2][1] = c2[1];
11840         decal->color4f[2][2] = c2[2];
11841         decal->color4f[2][3] = 1;
11842         decal->vertex3f[0][0] = v0[0];
11843         decal->vertex3f[0][1] = v0[1];
11844         decal->vertex3f[0][2] = v0[2];
11845         decal->vertex3f[1][0] = v1[0];
11846         decal->vertex3f[1][1] = v1[1];
11847         decal->vertex3f[1][2] = v1[2];
11848         decal->vertex3f[2][0] = v2[0];
11849         decal->vertex3f[2][1] = v2[1];
11850         decal->vertex3f[2][2] = v2[2];
11851         decal->texcoord2f[0][0] = t0[0];
11852         decal->texcoord2f[0][1] = t0[1];
11853         decal->texcoord2f[1][0] = t1[0];
11854         decal->texcoord2f[1][1] = t1[1];
11855         decal->texcoord2f[2][0] = t2[0];
11856         decal->texcoord2f[2][1] = t2[1];
11857         TriangleNormal(v0, v1, v2, decal->plane);
11858         VectorNormalize(decal->plane);
11859         decal->plane[3] = DotProduct(v0, decal->plane);
11860 }
11861
11862 extern cvar_t cl_decals_bias;
11863 extern cvar_t cl_decals_models;
11864 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11865 // baseparms, parms, temps
11866 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)
11867 {
11868         int cornerindex;
11869         int index;
11870         float v[9][3];
11871         const float *vertex3f;
11872         const float *normal3f;
11873         int numpoints;
11874         float points[2][9][3];
11875         float temp[3];
11876         float tc[9][2];
11877         float f;
11878         float c[9][4];
11879         const int *e;
11880
11881         e = rsurface.modelelement3i + 3*triangleindex;
11882
11883         vertex3f = rsurface.modelvertex3f;
11884         normal3f = rsurface.modelnormal3f;
11885
11886         if (normal3f)
11887         {
11888                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11889                 {
11890                         index = 3*e[cornerindex];
11891                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11892                 }
11893         }
11894         else
11895         {
11896                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11897                 {
11898                         index = 3*e[cornerindex];
11899                         VectorCopy(vertex3f + index, v[cornerindex]);
11900                 }
11901         }
11902
11903         // cull backfaces
11904         //TriangleNormal(v[0], v[1], v[2], normal);
11905         //if (DotProduct(normal, localnormal) < 0.0f)
11906         //      continue;
11907         // clip by each of the box planes formed from the projection matrix
11908         // if anything survives, we emit the decal
11909         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]);
11910         if (numpoints < 3)
11911                 return;
11912         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]);
11913         if (numpoints < 3)
11914                 return;
11915         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]);
11916         if (numpoints < 3)
11917                 return;
11918         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]);
11919         if (numpoints < 3)
11920                 return;
11921         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]);
11922         if (numpoints < 3)
11923                 return;
11924         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]);
11925         if (numpoints < 3)
11926                 return;
11927         // some part of the triangle survived, so we have to accept it...
11928         if (dynamic)
11929         {
11930                 // dynamic always uses the original triangle
11931                 numpoints = 3;
11932                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11933                 {
11934                         index = 3*e[cornerindex];
11935                         VectorCopy(vertex3f + index, v[cornerindex]);
11936                 }
11937         }
11938         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11939         {
11940                 // convert vertex positions to texcoords
11941                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11942                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11943                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11944                 // calculate distance fade from the projection origin
11945                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11946                 f = bound(0.0f, f, 1.0f);
11947                 c[cornerindex][0] = r * f;
11948                 c[cornerindex][1] = g * f;
11949                 c[cornerindex][2] = b * f;
11950                 c[cornerindex][3] = 1.0f;
11951                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11952         }
11953         if (dynamic)
11954                 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);
11955         else
11956                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11957                         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);
11958 }
11959 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)
11960 {
11961         matrix4x4_t projection;
11962         decalsystem_t *decalsystem;
11963         qboolean dynamic;
11964         dp_model_t *model;
11965         const msurface_t *surface;
11966         const msurface_t *surfaces;
11967         const int *surfacelist;
11968         const texture_t *texture;
11969         int numtriangles;
11970         int numsurfacelist;
11971         int surfacelistindex;
11972         int surfaceindex;
11973         int triangleindex;
11974         float localorigin[3];
11975         float localnormal[3];
11976         float localmins[3];
11977         float localmaxs[3];
11978         float localsize;
11979         //float normal[3];
11980         float planes[6][4];
11981         float angles[3];
11982         bih_t *bih;
11983         int bih_triangles_count;
11984         int bih_triangles[256];
11985         int bih_surfaces[256];
11986
11987         decalsystem = &ent->decalsystem;
11988         model = ent->model;
11989         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11990         {
11991                 R_DecalSystem_Reset(&ent->decalsystem);
11992                 return;
11993         }
11994
11995         if (!model->brush.data_leafs && !cl_decals_models.integer)
11996         {
11997                 if (decalsystem->model)
11998                         R_DecalSystem_Reset(decalsystem);
11999                 return;
12000         }
12001
12002         if (decalsystem->model != model)
12003                 R_DecalSystem_Reset(decalsystem);
12004         decalsystem->model = model;
12005
12006         RSurf_ActiveModelEntity(ent, true, false, false);
12007
12008         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12009         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12010         VectorNormalize(localnormal);
12011         localsize = worldsize*rsurface.inversematrixscale;
12012         localmins[0] = localorigin[0] - localsize;
12013         localmins[1] = localorigin[1] - localsize;
12014         localmins[2] = localorigin[2] - localsize;
12015         localmaxs[0] = localorigin[0] + localsize;
12016         localmaxs[1] = localorigin[1] + localsize;
12017         localmaxs[2] = localorigin[2] + localsize;
12018
12019         //VectorCopy(localnormal, planes[4]);
12020         //VectorVectors(planes[4], planes[2], planes[0]);
12021         AnglesFromVectors(angles, localnormal, NULL, false);
12022         AngleVectors(angles, planes[0], planes[2], planes[4]);
12023         VectorNegate(planes[0], planes[1]);
12024         VectorNegate(planes[2], planes[3]);
12025         VectorNegate(planes[4], planes[5]);
12026         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12027         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12028         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12029         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12030         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12031         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12032
12033 #if 1
12034 // works
12035 {
12036         matrix4x4_t forwardprojection;
12037         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12038         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12039 }
12040 #else
12041 // broken
12042 {
12043         float projectionvector[4][3];
12044         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12045         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12046         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12047         projectionvector[0][0] = planes[0][0] * ilocalsize;
12048         projectionvector[0][1] = planes[1][0] * ilocalsize;
12049         projectionvector[0][2] = planes[2][0] * ilocalsize;
12050         projectionvector[1][0] = planes[0][1] * ilocalsize;
12051         projectionvector[1][1] = planes[1][1] * ilocalsize;
12052         projectionvector[1][2] = planes[2][1] * ilocalsize;
12053         projectionvector[2][0] = planes[0][2] * ilocalsize;
12054         projectionvector[2][1] = planes[1][2] * ilocalsize;
12055         projectionvector[2][2] = planes[2][2] * ilocalsize;
12056         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12057         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12058         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12059         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12060 }
12061 #endif
12062
12063         dynamic = model->surfmesh.isanimated;
12064         numsurfacelist = model->nummodelsurfaces;
12065         surfacelist = model->sortedmodelsurfaces;
12066         surfaces = model->data_surfaces;
12067
12068         bih = NULL;
12069         bih_triangles_count = -1;
12070         if(!dynamic)
12071         {
12072                 if(model->render_bih.numleafs)
12073                         bih = &model->render_bih;
12074                 else if(model->collision_bih.numleafs)
12075                         bih = &model->collision_bih;
12076         }
12077         if(bih)
12078                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12079         if(bih_triangles_count == 0)
12080                 return;
12081         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12082                 return;
12083         if(bih_triangles_count > 0)
12084         {
12085                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12086                 {
12087                         surfaceindex = bih_surfaces[triangleindex];
12088                         surface = surfaces + surfaceindex;
12089                         texture = surface->texture;
12090                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12091                                 continue;
12092                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12093                                 continue;
12094                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12095                 }
12096         }
12097         else
12098         {
12099                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12100                 {
12101                         surfaceindex = surfacelist[surfacelistindex];
12102                         surface = surfaces + surfaceindex;
12103                         // check cull box first because it rejects more than any other check
12104                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12105                                 continue;
12106                         // skip transparent surfaces
12107                         texture = surface->texture;
12108                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12109                                 continue;
12110                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12111                                 continue;
12112                         numtriangles = surface->num_triangles;
12113                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12114                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12115                 }
12116         }
12117 }
12118
12119 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12120 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)
12121 {
12122         int renderentityindex;
12123         float worldmins[3];
12124         float worldmaxs[3];
12125         entity_render_t *ent;
12126
12127         if (!cl_decals_newsystem.integer)
12128                 return;
12129
12130         worldmins[0] = worldorigin[0] - worldsize;
12131         worldmins[1] = worldorigin[1] - worldsize;
12132         worldmins[2] = worldorigin[2] - worldsize;
12133         worldmaxs[0] = worldorigin[0] + worldsize;
12134         worldmaxs[1] = worldorigin[1] + worldsize;
12135         worldmaxs[2] = worldorigin[2] + worldsize;
12136
12137         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12138
12139         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12140         {
12141                 ent = r_refdef.scene.entities[renderentityindex];
12142                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12143                         continue;
12144
12145                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12146         }
12147 }
12148
12149 typedef struct r_decalsystem_splatqueue_s
12150 {
12151         vec3_t worldorigin;
12152         vec3_t worldnormal;
12153         float color[4];
12154         float tcrange[4];
12155         float worldsize;
12156         unsigned int decalsequence;
12157 }
12158 r_decalsystem_splatqueue_t;
12159
12160 int r_decalsystem_numqueued = 0;
12161 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12162
12163 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)
12164 {
12165         r_decalsystem_splatqueue_t *queue;
12166
12167         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12168                 return;
12169
12170         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12171         VectorCopy(worldorigin, queue->worldorigin);
12172         VectorCopy(worldnormal, queue->worldnormal);
12173         Vector4Set(queue->color, r, g, b, a);
12174         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12175         queue->worldsize = worldsize;
12176         queue->decalsequence = cl.decalsequence++;
12177 }
12178
12179 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12180 {
12181         int i;
12182         r_decalsystem_splatqueue_t *queue;
12183
12184         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12185                 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);
12186         r_decalsystem_numqueued = 0;
12187 }
12188
12189 extern cvar_t cl_decals_max;
12190 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12191 {
12192         int i;
12193         decalsystem_t *decalsystem = &ent->decalsystem;
12194         int numdecals;
12195         unsigned int killsequence;
12196         tridecal_t *decal;
12197         float frametime;
12198         float lifetime;
12199
12200         if (!decalsystem->numdecals)
12201                 return;
12202
12203         if (r_showsurfaces.integer)
12204                 return;
12205
12206         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12207         {
12208                 R_DecalSystem_Reset(decalsystem);
12209                 return;
12210         }
12211
12212         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12213         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12214
12215         if (decalsystem->lastupdatetime)
12216                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12217         else
12218                 frametime = 0;
12219         decalsystem->lastupdatetime = r_refdef.scene.time;
12220         numdecals = decalsystem->numdecals;
12221
12222         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12223         {
12224                 if (decal->color4f[0][3])
12225                 {
12226                         decal->lived += frametime;
12227                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12228                         {
12229                                 memset(decal, 0, sizeof(*decal));
12230                                 if (decalsystem->freedecal > i)
12231                                         decalsystem->freedecal = i;
12232                         }
12233                 }
12234         }
12235         decal = decalsystem->decals;
12236         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12237                 numdecals--;
12238
12239         // collapse the array by shuffling the tail decals into the gaps
12240         for (;;)
12241         {
12242                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12243                         decalsystem->freedecal++;
12244                 if (decalsystem->freedecal == numdecals)
12245                         break;
12246                 decal[decalsystem->freedecal] = decal[--numdecals];
12247         }
12248
12249         decalsystem->numdecals = numdecals;
12250
12251         if (numdecals <= 0)
12252         {
12253                 // if there are no decals left, reset decalsystem
12254                 R_DecalSystem_Reset(decalsystem);
12255         }
12256 }
12257
12258 extern skinframe_t *decalskinframe;
12259 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12260 {
12261         int i;
12262         decalsystem_t *decalsystem = &ent->decalsystem;
12263         int numdecals;
12264         tridecal_t *decal;
12265         float faderate;
12266         float alpha;
12267         float *v3f;
12268         float *c4f;
12269         float *t2f;
12270         const int *e;
12271         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12272         int numtris = 0;
12273
12274         numdecals = decalsystem->numdecals;
12275         if (!numdecals)
12276                 return;
12277
12278         if (r_showsurfaces.integer)
12279                 return;
12280
12281         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12282         {
12283                 R_DecalSystem_Reset(decalsystem);
12284                 return;
12285         }
12286
12287         // if the model is static it doesn't matter what value we give for
12288         // wantnormals and wanttangents, so this logic uses only rules applicable
12289         // to a model, knowing that they are meaningless otherwise
12290         if (ent == r_refdef.scene.worldentity)
12291                 RSurf_ActiveWorldEntity();
12292         else
12293                 RSurf_ActiveModelEntity(ent, false, false, false);
12294
12295         decalsystem->lastupdatetime = r_refdef.scene.time;
12296
12297         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12298
12299         // update vertex positions for animated models
12300         v3f = decalsystem->vertex3f;
12301         c4f = decalsystem->color4f;
12302         t2f = decalsystem->texcoord2f;
12303         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12304         {
12305                 if (!decal->color4f[0][3])
12306                         continue;
12307
12308                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12309                         continue;
12310
12311                 // skip backfaces
12312                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12313                         continue;
12314
12315                 // update color values for fading decals
12316                 if (decal->lived >= cl_decals_time.value)
12317                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12318                 else
12319                         alpha = 1.0f;
12320
12321                 c4f[ 0] = decal->color4f[0][0] * alpha;
12322                 c4f[ 1] = decal->color4f[0][1] * alpha;
12323                 c4f[ 2] = decal->color4f[0][2] * alpha;
12324                 c4f[ 3] = 1;
12325                 c4f[ 4] = decal->color4f[1][0] * alpha;
12326                 c4f[ 5] = decal->color4f[1][1] * alpha;
12327                 c4f[ 6] = decal->color4f[1][2] * alpha;
12328                 c4f[ 7] = 1;
12329                 c4f[ 8] = decal->color4f[2][0] * alpha;
12330                 c4f[ 9] = decal->color4f[2][1] * alpha;
12331                 c4f[10] = decal->color4f[2][2] * alpha;
12332                 c4f[11] = 1;
12333
12334                 t2f[0] = decal->texcoord2f[0][0];
12335                 t2f[1] = decal->texcoord2f[0][1];
12336                 t2f[2] = decal->texcoord2f[1][0];
12337                 t2f[3] = decal->texcoord2f[1][1];
12338                 t2f[4] = decal->texcoord2f[2][0];
12339                 t2f[5] = decal->texcoord2f[2][1];
12340
12341                 // update vertex positions for animated models
12342                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12343                 {
12344                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12345                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12346                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12347                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12348                 }
12349                 else
12350                 {
12351                         VectorCopy(decal->vertex3f[0], v3f);
12352                         VectorCopy(decal->vertex3f[1], v3f + 3);
12353                         VectorCopy(decal->vertex3f[2], v3f + 6);
12354                 }
12355
12356                 if (r_refdef.fogenabled)
12357                 {
12358                         alpha = RSurf_FogVertex(v3f);
12359                         VectorScale(c4f, alpha, c4f);
12360                         alpha = RSurf_FogVertex(v3f + 3);
12361                         VectorScale(c4f + 4, alpha, c4f + 4);
12362                         alpha = RSurf_FogVertex(v3f + 6);
12363                         VectorScale(c4f + 8, alpha, c4f + 8);
12364                 }
12365
12366                 v3f += 9;
12367                 c4f += 12;
12368                 t2f += 6;
12369                 numtris++;
12370         }
12371
12372         if (numtris > 0)
12373         {
12374                 r_refdef.stats[r_stat_drawndecals] += numtris;
12375
12376                 // now render the decals all at once
12377                 // (this assumes they all use one particle font texture!)
12378                 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);
12379 //              R_Mesh_ResetTextureState();
12380                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12381                 GL_DepthMask(false);
12382                 GL_DepthRange(0, 1);
12383                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12384                 GL_DepthTest(true);
12385                 GL_CullFace(GL_NONE);
12386                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12387                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12388                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12389         }
12390 }
12391
12392 static void R_DrawModelDecals(void)
12393 {
12394         int i, numdecals;
12395
12396         // fade faster when there are too many decals
12397         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12398         for (i = 0;i < r_refdef.scene.numentities;i++)
12399                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12400
12401         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12402         for (i = 0;i < r_refdef.scene.numentities;i++)
12403                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12404                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12405
12406         R_DecalSystem_ApplySplatEntitiesQueue();
12407
12408         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12409         for (i = 0;i < r_refdef.scene.numentities;i++)
12410                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12411
12412         r_refdef.stats[r_stat_totaldecals] += numdecals;
12413
12414         if (r_showsurfaces.integer)
12415                 return;
12416
12417         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12418
12419         for (i = 0;i < r_refdef.scene.numentities;i++)
12420         {
12421                 if (!r_refdef.viewcache.entityvisible[i])
12422                         continue;
12423                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12424                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12425         }
12426 }
12427
12428 extern cvar_t mod_collision_bih;
12429 static void R_DrawDebugModel(void)
12430 {
12431         entity_render_t *ent = rsurface.entity;
12432         int i, j, flagsmask;
12433         const msurface_t *surface;
12434         dp_model_t *model = ent->model;
12435
12436         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12437                 return;
12438
12439         if (r_showoverdraw.value > 0)
12440         {
12441                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12442                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12443                 R_SetupShader_Generic_NoTexture(false, false);
12444                 GL_DepthTest(false);
12445                 GL_DepthMask(false);
12446                 GL_DepthRange(0, 1);
12447                 GL_BlendFunc(GL_ONE, GL_ONE);
12448                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12449                 {
12450                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12451                                 continue;
12452                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12453                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12454                         {
12455                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12456                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12457                                 if (!rsurface.texture->currentlayers->depthmask)
12458                                         GL_Color(c, 0, 0, 1.0f);
12459                                 else if (ent == r_refdef.scene.worldentity)
12460                                         GL_Color(c, c, c, 1.0f);
12461                                 else
12462                                         GL_Color(0, c, 0, 1.0f);
12463                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12464                                 RSurf_DrawBatch();
12465                         }
12466                 }
12467                 rsurface.texture = NULL;
12468         }
12469
12470         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12471
12472 //      R_Mesh_ResetTextureState();
12473         R_SetupShader_Generic_NoTexture(false, false);
12474         GL_DepthRange(0, 1);
12475         GL_DepthTest(!r_showdisabledepthtest.integer);
12476         GL_DepthMask(false);
12477         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12478
12479         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12480         {
12481                 int triangleindex;
12482                 int bihleafindex;
12483                 qboolean cullbox = false;
12484                 const q3mbrush_t *brush;
12485                 const bih_t *bih = &model->collision_bih;
12486                 const bih_leaf_t *bihleaf;
12487                 float vertex3f[3][3];
12488                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12489                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12490                 {
12491                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12492                                 continue;
12493                         switch (bihleaf->type)
12494                         {
12495                         case BIH_BRUSH:
12496                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12497                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12498                                 {
12499                                         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);
12500                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12501                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12502                                 }
12503                                 break;
12504                         case BIH_COLLISIONTRIANGLE:
12505                                 triangleindex = bihleaf->itemindex;
12506                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12507                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12508                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12509                                 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);
12510                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12511                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12512                                 break;
12513                         case BIH_RENDERTRIANGLE:
12514                                 triangleindex = bihleaf->itemindex;
12515                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12516                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12517                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12518                                 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);
12519                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12520                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12521                                 break;
12522                         }
12523                 }
12524         }
12525
12526         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12527
12528 #ifndef USE_GLES2
12529         if (r_showtris.integer && qglPolygonMode)
12530         {
12531                 if (r_showdisabledepthtest.integer)
12532                 {
12533                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12534                         GL_DepthMask(false);
12535                 }
12536                 else
12537                 {
12538                         GL_BlendFunc(GL_ONE, GL_ZERO);
12539                         GL_DepthMask(true);
12540                 }
12541                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12542                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12543                 {
12544                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12545                                 continue;
12546                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12547                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12548                         {
12549                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12550                                 if (!rsurface.texture->currentlayers->depthmask)
12551                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12552                                 else if (ent == r_refdef.scene.worldentity)
12553                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12554                                 else
12555                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12556                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12557                                 RSurf_DrawBatch();
12558                         }
12559                 }
12560                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12561                 rsurface.texture = NULL;
12562         }
12563
12564         if (r_shownormals.value != 0 && qglBegin)
12565         {
12566                 int l, k;
12567                 vec3_t v;
12568                 if (r_showdisabledepthtest.integer)
12569                 {
12570                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12571                         GL_DepthMask(false);
12572                 }
12573                 else
12574                 {
12575                         GL_BlendFunc(GL_ONE, GL_ZERO);
12576                         GL_DepthMask(true);
12577                 }
12578                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12579                 {
12580                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12581                                 continue;
12582                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12583                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12584                         {
12585                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12586                                 qglBegin(GL_LINES);
12587                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12588                                 {
12589                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12590                                         {
12591                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12592                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12593                                                 qglVertex3f(v[0], v[1], v[2]);
12594                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12595                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12596                                                 qglVertex3f(v[0], v[1], v[2]);
12597                                         }
12598                                 }
12599                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12600                                 {
12601                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12602                                         {
12603                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12604                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12605                                                 qglVertex3f(v[0], v[1], v[2]);
12606                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12607                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12608                                                 qglVertex3f(v[0], v[1], v[2]);
12609                                         }
12610                                 }
12611                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12612                                 {
12613                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12614                                         {
12615                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12616                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12617                                                 qglVertex3f(v[0], v[1], v[2]);
12618                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12619                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12620                                                 qglVertex3f(v[0], v[1], v[2]);
12621                                         }
12622                                 }
12623                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12624                                 {
12625                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12626                                         {
12627                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12628                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12629                                                 qglVertex3f(v[0], v[1], v[2]);
12630                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12631                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12632                                                 qglVertex3f(v[0], v[1], v[2]);
12633                                         }
12634                                 }
12635                                 qglEnd();
12636                                 CHECKGLERROR
12637                         }
12638                 }
12639                 rsurface.texture = NULL;
12640         }
12641 #endif
12642 }
12643
12644 int r_maxsurfacelist = 0;
12645 const msurface_t **r_surfacelist = NULL;
12646 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12647 {
12648         int i, j, endj, flagsmask;
12649         dp_model_t *model = r_refdef.scene.worldmodel;
12650         msurface_t *surfaces;
12651         unsigned char *update;
12652         int numsurfacelist = 0;
12653         if (model == NULL)
12654                 return;
12655
12656         if (r_maxsurfacelist < model->num_surfaces)
12657         {
12658                 r_maxsurfacelist = model->num_surfaces;
12659                 if (r_surfacelist)
12660                         Mem_Free((msurface_t**)r_surfacelist);
12661                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12662         }
12663
12664         RSurf_ActiveWorldEntity();
12665
12666         surfaces = model->data_surfaces;
12667         update = model->brushq1.lightmapupdateflags;
12668
12669         // update light styles on this submodel
12670         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12671         {
12672                 model_brush_lightstyleinfo_t *style;
12673                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12674                 {
12675                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12676                         {
12677                                 int *list = style->surfacelist;
12678                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12679                                 for (j = 0;j < style->numsurfaces;j++)
12680                                         update[list[j]] = true;
12681                         }
12682                 }
12683         }
12684
12685         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12686
12687         if (debug)
12688         {
12689                 R_DrawDebugModel();
12690                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12691                 return;
12692         }
12693
12694         rsurface.lightmaptexture = NULL;
12695         rsurface.deluxemaptexture = NULL;
12696         rsurface.uselightmaptexture = false;
12697         rsurface.texture = NULL;
12698         rsurface.rtlight = NULL;
12699         numsurfacelist = 0;
12700         // add visible surfaces to draw list
12701         for (i = 0;i < model->nummodelsurfaces;i++)
12702         {
12703                 j = model->sortedmodelsurfaces[i];
12704                 if (r_refdef.viewcache.world_surfacevisible[j])
12705                         r_surfacelist[numsurfacelist++] = surfaces + j;
12706         }
12707         // update lightmaps if needed
12708         if (model->brushq1.firstrender)
12709         {
12710                 model->brushq1.firstrender = false;
12711                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12712                         if (update[j])
12713                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12714         }
12715         else if (update)
12716         {
12717                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12718                         if (r_refdef.viewcache.world_surfacevisible[j])
12719                                 if (update[j])
12720                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12721         }
12722         // don't do anything if there were no surfaces
12723         if (!numsurfacelist)
12724         {
12725                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12726                 return;
12727         }
12728         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12729
12730         // add to stats if desired
12731         if (r_speeds.integer && !skysurfaces && !depthonly)
12732         {
12733                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12734                 for (j = 0;j < numsurfacelist;j++)
12735                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12736         }
12737
12738         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12739 }
12740
12741 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12742 {
12743         int i, j, endj, flagsmask;
12744         dp_model_t *model = ent->model;
12745         msurface_t *surfaces;
12746         unsigned char *update;
12747         int numsurfacelist = 0;
12748         if (model == NULL)
12749                 return;
12750
12751         if (r_maxsurfacelist < model->num_surfaces)
12752         {
12753                 r_maxsurfacelist = model->num_surfaces;
12754                 if (r_surfacelist)
12755                         Mem_Free((msurface_t **)r_surfacelist);
12756                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12757         }
12758
12759         // if the model is static it doesn't matter what value we give for
12760         // wantnormals and wanttangents, so this logic uses only rules applicable
12761         // to a model, knowing that they are meaningless otherwise
12762         if (ent == r_refdef.scene.worldentity)
12763                 RSurf_ActiveWorldEntity();
12764         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12765                 RSurf_ActiveModelEntity(ent, false, false, false);
12766         else if (prepass)
12767                 RSurf_ActiveModelEntity(ent, true, true, true);
12768         else if (depthonly)
12769         {
12770                 switch (vid.renderpath)
12771                 {
12772                 case RENDERPATH_GL20:
12773                 case RENDERPATH_D3D9:
12774                 case RENDERPATH_D3D10:
12775                 case RENDERPATH_D3D11:
12776                 case RENDERPATH_SOFT:
12777                 case RENDERPATH_GLES2:
12778                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12779                         break;
12780                 case RENDERPATH_GL11:
12781                 case RENDERPATH_GL13:
12782                 case RENDERPATH_GLES1:
12783                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12784                         break;
12785                 }
12786         }
12787         else
12788         {
12789                 switch (vid.renderpath)
12790                 {
12791                 case RENDERPATH_GL20:
12792                 case RENDERPATH_D3D9:
12793                 case RENDERPATH_D3D10:
12794                 case RENDERPATH_D3D11:
12795                 case RENDERPATH_SOFT:
12796                 case RENDERPATH_GLES2:
12797                         RSurf_ActiveModelEntity(ent, true, true, false);
12798                         break;
12799                 case RENDERPATH_GL11:
12800                 case RENDERPATH_GL13:
12801                 case RENDERPATH_GLES1:
12802                         RSurf_ActiveModelEntity(ent, true, false, false);
12803                         break;
12804                 }
12805         }
12806
12807         surfaces = model->data_surfaces;
12808         update = model->brushq1.lightmapupdateflags;
12809
12810         // update light styles
12811         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12812         {
12813                 model_brush_lightstyleinfo_t *style;
12814                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12815                 {
12816                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12817                         {
12818                                 int *list = style->surfacelist;
12819                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12820                                 for (j = 0;j < style->numsurfaces;j++)
12821                                         update[list[j]] = true;
12822                         }
12823                 }
12824         }
12825
12826         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12827
12828         if (debug)
12829         {
12830                 R_DrawDebugModel();
12831                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12832                 return;
12833         }
12834
12835         rsurface.lightmaptexture = NULL;
12836         rsurface.deluxemaptexture = NULL;
12837         rsurface.uselightmaptexture = false;
12838         rsurface.texture = NULL;
12839         rsurface.rtlight = NULL;
12840         numsurfacelist = 0;
12841         // add visible surfaces to draw list
12842         for (i = 0;i < model->nummodelsurfaces;i++)
12843                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12844         // don't do anything if there were no surfaces
12845         if (!numsurfacelist)
12846         {
12847                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12848                 return;
12849         }
12850         // update lightmaps if needed
12851         if (update)
12852         {
12853                 int updated = 0;
12854                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12855                 {
12856                         if (update[j])
12857                         {
12858                                 updated++;
12859                                 R_BuildLightMap(ent, surfaces + j);
12860                         }
12861                 }
12862         }
12863
12864         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12865
12866         // add to stats if desired
12867         if (r_speeds.integer && !skysurfaces && !depthonly)
12868         {
12869                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12870                 for (j = 0;j < numsurfacelist;j++)
12871                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12872         }
12873
12874         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12875 }
12876
12877 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12878 {
12879         static texture_t texture;
12880         static msurface_t surface;
12881         const msurface_t *surfacelist = &surface;
12882
12883         // fake enough texture and surface state to render this geometry
12884
12885         texture.update_lastrenderframe = -1; // regenerate this texture
12886         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12887         texture.basealpha = 1.0f;
12888         texture.currentskinframe = skinframe;
12889         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12890         texture.offsetmapping = OFFSETMAPPING_OFF;
12891         texture.offsetscale = 1;
12892         texture.specularscalemod = 1;
12893         texture.specularpowermod = 1;
12894         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12895         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12896         // JUST GREP FOR "specularscalemod = 1".
12897
12898         surface.texture = &texture;
12899         surface.num_triangles = numtriangles;
12900         surface.num_firsttriangle = firsttriangle;
12901         surface.num_vertices = numvertices;
12902         surface.num_firstvertex = firstvertex;
12903
12904         // now render it
12905         rsurface.texture = R_GetCurrentTexture(surface.texture);
12906         rsurface.lightmaptexture = NULL;
12907         rsurface.deluxemaptexture = NULL;
12908         rsurface.uselightmaptexture = false;
12909         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12910 }
12911
12912 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)
12913 {
12914         static msurface_t surface;
12915         const msurface_t *surfacelist = &surface;
12916
12917         // fake enough texture and surface state to render this geometry
12918         surface.texture = texture;
12919         surface.num_triangles = numtriangles;
12920         surface.num_firsttriangle = firsttriangle;
12921         surface.num_vertices = numvertices;
12922         surface.num_firstvertex = firstvertex;
12923
12924         // now render it
12925         rsurface.texture = R_GetCurrentTexture(surface.texture);
12926         rsurface.lightmaptexture = NULL;
12927         rsurface.deluxemaptexture = NULL;
12928         rsurface.uselightmaptexture = false;
12929         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12930 }