]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Mark a bug as done.
[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
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
83
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
119
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
123
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
150
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
159
160 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)"};
161 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"};
162
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
166
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
176
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196
197 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)"};
198 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)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 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)"};
207
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
212
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
215
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
222
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
233
234 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"};
235
236 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"};
237
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
239
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
241
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
246
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
249
250 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."};
251
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
254 {
255         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
259 };
260
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
263
264 extern qboolean v_flipped_state;
265
266 r_framebufferstate_t r_fb;
267
268 /// shadow volume bsp struct with automatically growing nodes buffer
269 svbsp_t r_svbsp;
270
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
272
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
286
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
289 {
290         char basename[64];
291         rtexture_t *texture;
292 }
293 cubemapinfo_t;
294
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
297
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
301
302 typedef struct r_qwskincache_s
303 {
304         char name[MAX_QPATH];
305         skinframe_t *skinframe;
306 }
307 r_qwskincache_t;
308
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
311
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
316 {
317         0, 0, 0,
318         1, 0, 0,
319         1, 1, 0,
320         0, 1, 0
321 };
322 const float r_d3dscreenvertex3f[12] =
323 {
324         0, 1, 0,
325         1, 1, 0,
326         1, 0, 0,
327         0, 0, 0
328 };
329
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
331 {
332         int i;
333         for (i = 0;i < verts;i++)
334         {
335                 out[0] = in[0] * r;
336                 out[1] = in[1] * g;
337                 out[2] = in[2] * b;
338                 out[3] = in[3];
339                 in += 4;
340                 out += 4;
341         }
342 }
343
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
345 {
346         int i;
347         for (i = 0;i < verts;i++)
348         {
349                 out[0] = r;
350                 out[1] = g;
351                 out[2] = b;
352                 out[3] = a;
353                 out += 4;
354         }
355 }
356
357 // FIXME: move this to client?
358 void FOG_clear(void)
359 {
360         if (gamemode == GAME_NEHAHRA)
361         {
362                 Cvar_Set("gl_fogenable", "0");
363                 Cvar_Set("gl_fogdensity", "0.2");
364                 Cvar_Set("gl_fogred", "0.3");
365                 Cvar_Set("gl_foggreen", "0.3");
366                 Cvar_Set("gl_fogblue", "0.3");
367         }
368         r_refdef.fog_density = 0;
369         r_refdef.fog_red = 0;
370         r_refdef.fog_green = 0;
371         r_refdef.fog_blue = 0;
372         r_refdef.fog_alpha = 1;
373         r_refdef.fog_start = 0;
374         r_refdef.fog_end = 16384;
375         r_refdef.fog_height = 1<<30;
376         r_refdef.fog_fadedepth = 128;
377         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
378 }
379
380 static void R_BuildBlankTextures(void)
381 {
382         unsigned char data[4];
383         data[2] = 128; // normal X
384         data[1] = 128; // normal Y
385         data[0] = 255; // normal Z
386         data[3] = 255; // height
387         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 255;
389         data[1] = 255;
390         data[2] = 255;
391         data[3] = 255;
392         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393         data[0] = 128;
394         data[1] = 128;
395         data[2] = 128;
396         data[3] = 255;
397         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 0;
399         data[1] = 0;
400         data[2] = 0;
401         data[3] = 255;
402         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNoTexture(void)
406 {
407         int x, y;
408         unsigned char pix[16][16][4];
409         // this makes a light grey/dark grey checkerboard texture
410         for (y = 0;y < 16;y++)
411         {
412                 for (x = 0;x < 16;x++)
413                 {
414                         if ((y < 8) ^ (x < 8))
415                         {
416                                 pix[y][x][0] = 128;
417                                 pix[y][x][1] = 128;
418                                 pix[y][x][2] = 128;
419                                 pix[y][x][3] = 255;
420                         }
421                         else
422                         {
423                                 pix[y][x][0] = 64;
424                                 pix[y][x][1] = 64;
425                                 pix[y][x][2] = 64;
426                                 pix[y][x][3] = 255;
427                         }
428                 }
429         }
430         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildWhiteCube(void)
434 {
435         unsigned char data[6*1*1*4];
436         memset(data, 255, sizeof(data));
437         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
438 }
439
440 static void R_BuildNormalizationCube(void)
441 {
442         int x, y, side;
443         vec3_t v;
444         vec_t s, t, intensity;
445 #define NORMSIZE 64
446         unsigned char *data;
447         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448         for (side = 0;side < 6;side++)
449         {
450                 for (y = 0;y < NORMSIZE;y++)
451                 {
452                         for (x = 0;x < NORMSIZE;x++)
453                         {
454                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
456                                 switch(side)
457                                 {
458                                 default:
459                                 case 0:
460                                         v[0] = 1;
461                                         v[1] = -t;
462                                         v[2] = -s;
463                                         break;
464                                 case 1:
465                                         v[0] = -1;
466                                         v[1] = -t;
467                                         v[2] = s;
468                                         break;
469                                 case 2:
470                                         v[0] = s;
471                                         v[1] = 1;
472                                         v[2] = t;
473                                         break;
474                                 case 3:
475                                         v[0] = s;
476                                         v[1] = -1;
477                                         v[2] = -t;
478                                         break;
479                                 case 4:
480                                         v[0] = s;
481                                         v[1] = -t;
482                                         v[2] = 1;
483                                         break;
484                                 case 5:
485                                         v[0] = -s;
486                                         v[1] = -t;
487                                         v[2] = -1;
488                                         break;
489                                 }
490                                 intensity = 127.0f / sqrt(DotProduct(v, v));
491                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494                                 data[((side*64+y)*64+x)*4+3] = 255;
495                         }
496                 }
497         }
498         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499         Mem_Free(data);
500 }
501
502 static void R_BuildFogTexture(void)
503 {
504         int x, b;
505 #define FOGWIDTH 256
506         unsigned char data1[FOGWIDTH][4];
507         //unsigned char data2[FOGWIDTH][4];
508         double d, r, alpha;
509
510         r_refdef.fogmasktable_start = r_refdef.fog_start;
511         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512         r_refdef.fogmasktable_range = r_refdef.fogrange;
513         r_refdef.fogmasktable_density = r_refdef.fog_density;
514
515         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
517         {
518                 d = (x * r - r_refdef.fogmasktable_start);
519                 if(developer_extra.integer)
520                         Con_DPrintf("%f ", d);
521                 d = max(0, d);
522                 if (r_fog_exp2.integer)
523                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
524                 else
525                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526                 if(developer_extra.integer)
527                         Con_DPrintf(" : %f ", alpha);
528                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529                 if(developer_extra.integer)
530                         Con_DPrintf(" = %f\n", alpha);
531                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
532         }
533
534         for (x = 0;x < FOGWIDTH;x++)
535         {
536                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537                 data1[x][0] = b;
538                 data1[x][1] = b;
539                 data1[x][2] = b;
540                 data1[x][3] = 255;
541                 //data2[x][0] = 255 - b;
542                 //data2[x][1] = 255 - b;
543                 //data2[x][2] = 255 - b;
544                 //data2[x][3] = 255;
545         }
546         if (r_texture_fogattenuation)
547         {
548                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
550         }
551         else
552         {
553                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
555         }
556 }
557
558 static void R_BuildFogHeightTexture(void)
559 {
560         unsigned char *inpixels;
561         int size;
562         int x;
563         int y;
564         int j;
565         float c[4];
566         float f;
567         inpixels = NULL;
568         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569         if (r_refdef.fogheighttexturename[0])
570                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
571         if (!inpixels)
572         {
573                 r_refdef.fog_height_tablesize = 0;
574                 if (r_texture_fogheighttexture)
575                         R_FreeTexture(r_texture_fogheighttexture);
576                 r_texture_fogheighttexture = NULL;
577                 if (r_refdef.fog_height_table2d)
578                         Mem_Free(r_refdef.fog_height_table2d);
579                 r_refdef.fog_height_table2d = NULL;
580                 if (r_refdef.fog_height_table1d)
581                         Mem_Free(r_refdef.fog_height_table1d);
582                 r_refdef.fog_height_table1d = NULL;
583                 return;
584         }
585         size = image_width;
586         r_refdef.fog_height_tablesize = size;
587         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
590         Mem_Free(inpixels);
591         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
592         // average fog color table accounting for every fog layer between a point
593         // and the camera.  (Note: attenuation is handled separately!)
594         for (y = 0;y < size;y++)
595         {
596                 for (x = 0;x < size;x++)
597                 {
598                         Vector4Clear(c);
599                         f = 0;
600                         if (x < y)
601                         {
602                                 for (j = x;j <= y;j++)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         else
609                         {
610                                 for (j = x;j >= y;j--)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         f = 1.0f / f;
617                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
621                 }
622         }
623         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
624 }
625
626 //=======================================================================================================================================================
627
628 static const char *builtinshaderstrings[] =
629 {
630 #include "shader_glsl.h"
631 0
632 };
633
634 const char *builtinhlslshaderstrings[] =
635 {
636 #include "shader_hlsl.h"
637 0
638 };
639
640 //=======================================================================================================================================================
641
642 typedef struct shaderpermutationinfo_s
643 {
644         const char *pretext;
645         const char *name;
646 }
647 shaderpermutationinfo_t;
648
649 typedef struct shadermodeinfo_s
650 {
651         const char *sourcebasename;
652         const char *extension;
653         const char **builtinshaderstrings;
654         const char *pretext;
655         const char *name;
656         char *filename;
657         char *builtinstring;
658         int builtincrc;
659 }
660 shadermodeinfo_t;
661
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
664 {
665         {"#define USEDIFFUSE\n", " diffuse"},
666         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
667         {"#define USEVIEWTINT\n", " viewtint"},
668         {"#define USECOLORMAPPING\n", " colormapping"},
669         {"#define USESATURATION\n", " saturation"},
670         {"#define USEFOGINSIDE\n", " foginside"},
671         {"#define USEFOGOUTSIDE\n", " fogoutside"},
672         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
673         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
674         {"#define USEGAMMARAMPS\n", " gammaramps"},
675         {"#define USECUBEFILTER\n", " cubefilter"},
676         {"#define USEGLOW\n", " glow"},
677         {"#define USEBLOOM\n", " bloom"},
678         {"#define USESPECULAR\n", " specular"},
679         {"#define USEPOSTPROCESSING\n", " postprocessing"},
680         {"#define USEREFLECTION\n", " reflection"},
681         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
682         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
683         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
684         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
685         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
686         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
687         {"#define USEALPHAKILL\n", " alphakill"},
688         {"#define USEREFLECTCUBE\n", " reflectcube"},
689         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
690         {"#define USEBOUNCEGRID\n", " bouncegrid"},
691         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
692         {"#define USETRIPPY\n", " trippy"},
693         {"#define USEDEPTHRGB\n", " depthrgb"},
694         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
695         {"#define USESKELETAL\n", " skeletal"},
696         {"#define USEOCCLUDE\n", " occlude"}
697 };
698
699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
700 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
701 {
702         // SHADERLANGUAGE_GLSL
703         {
704                 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
705                 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
706                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
708                 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
710                 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
711                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
714                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
715                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716                 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
717                 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
718                 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
719                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720                 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
721         },
722         // SHADERLANGUAGE_HLSL
723         {
724                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
725                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
726                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
727                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
728                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
729                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
730                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
731                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
732                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
733                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
734                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
735                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
736                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
737                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
738                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
739                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
740                 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
741         },
742 };
743
744 struct r_glsl_permutation_s;
745 typedef struct r_glsl_permutation_s
746 {
747         /// hash lookup data
748         struct r_glsl_permutation_s *hashnext;
749         unsigned int mode;
750         unsigned int permutation;
751
752         /// indicates if we have tried compiling this permutation already
753         qboolean compiled;
754         /// 0 if compilation failed
755         int program;
756         // texture units assigned to each detected uniform
757         int tex_Texture_First;
758         int tex_Texture_Second;
759         int tex_Texture_GammaRamps;
760         int tex_Texture_Normal;
761         int tex_Texture_Color;
762         int tex_Texture_Gloss;
763         int tex_Texture_Glow;
764         int tex_Texture_SecondaryNormal;
765         int tex_Texture_SecondaryColor;
766         int tex_Texture_SecondaryGloss;
767         int tex_Texture_SecondaryGlow;
768         int tex_Texture_Pants;
769         int tex_Texture_Shirt;
770         int tex_Texture_FogHeightTexture;
771         int tex_Texture_FogMask;
772         int tex_Texture_Lightmap;
773         int tex_Texture_Deluxemap;
774         int tex_Texture_Attenuation;
775         int tex_Texture_Cube;
776         int tex_Texture_Refraction;
777         int tex_Texture_Reflection;
778         int tex_Texture_ShadowMap2D;
779         int tex_Texture_CubeProjection;
780         int tex_Texture_ScreenNormalMap;
781         int tex_Texture_ScreenDiffuse;
782         int tex_Texture_ScreenSpecular;
783         int tex_Texture_ReflectMask;
784         int tex_Texture_ReflectCube;
785         int tex_Texture_BounceGrid;
786         /// locations of detected uniforms in program object, or -1 if not found
787         int loc_Texture_First;
788         int loc_Texture_Second;
789         int loc_Texture_GammaRamps;
790         int loc_Texture_Normal;
791         int loc_Texture_Color;
792         int loc_Texture_Gloss;
793         int loc_Texture_Glow;
794         int loc_Texture_SecondaryNormal;
795         int loc_Texture_SecondaryColor;
796         int loc_Texture_SecondaryGloss;
797         int loc_Texture_SecondaryGlow;
798         int loc_Texture_Pants;
799         int loc_Texture_Shirt;
800         int loc_Texture_FogHeightTexture;
801         int loc_Texture_FogMask;
802         int loc_Texture_Lightmap;
803         int loc_Texture_Deluxemap;
804         int loc_Texture_Attenuation;
805         int loc_Texture_Cube;
806         int loc_Texture_Refraction;
807         int loc_Texture_Reflection;
808         int loc_Texture_ShadowMap2D;
809         int loc_Texture_CubeProjection;
810         int loc_Texture_ScreenNormalMap;
811         int loc_Texture_ScreenDiffuse;
812         int loc_Texture_ScreenSpecular;
813         int loc_Texture_ReflectMask;
814         int loc_Texture_ReflectCube;
815         int loc_Texture_BounceGrid;
816         int loc_Alpha;
817         int loc_BloomBlur_Parameters;
818         int loc_ClientTime;
819         int loc_Color_Ambient;
820         int loc_Color_Diffuse;
821         int loc_Color_Specular;
822         int loc_Color_Glow;
823         int loc_Color_Pants;
824         int loc_Color_Shirt;
825         int loc_DeferredColor_Ambient;
826         int loc_DeferredColor_Diffuse;
827         int loc_DeferredColor_Specular;
828         int loc_DeferredMod_Diffuse;
829         int loc_DeferredMod_Specular;
830         int loc_DistortScaleRefractReflect;
831         int loc_EyePosition;
832         int loc_FogColor;
833         int loc_FogHeightFade;
834         int loc_FogPlane;
835         int loc_FogPlaneViewDist;
836         int loc_FogRangeRecip;
837         int loc_LightColor;
838         int loc_LightDir;
839         int loc_LightPosition;
840         int loc_OffsetMapping_ScaleSteps;
841         int loc_OffsetMapping_LodDistance;
842         int loc_OffsetMapping_Bias;
843         int loc_PixelSize;
844         int loc_ReflectColor;
845         int loc_ReflectFactor;
846         int loc_ReflectOffset;
847         int loc_RefractColor;
848         int loc_Saturation;
849         int loc_ScreenCenterRefractReflect;
850         int loc_ScreenScaleRefractReflect;
851         int loc_ScreenToDepth;
852         int loc_ShadowMap_Parameters;
853         int loc_ShadowMap_TextureScale;
854         int loc_SpecularPower;
855         int loc_Skeletal_Transform12;
856         int loc_UserVec1;
857         int loc_UserVec2;
858         int loc_UserVec3;
859         int loc_UserVec4;
860         int loc_ViewTintColor;
861         int loc_ViewToLight;
862         int loc_ModelToLight;
863         int loc_TexMatrix;
864         int loc_BackgroundTexMatrix;
865         int loc_ModelViewProjectionMatrix;
866         int loc_ModelViewMatrix;
867         int loc_PixelToScreenTexCoord;
868         int loc_ModelToReflectCube;
869         int loc_ShadowMapMatrix;
870         int loc_BloomColorSubtract;
871         int loc_NormalmapScrollBlend;
872         int loc_BounceGridMatrix;
873         int loc_BounceGridIntensity;
874         /// uniform block bindings
875         int ubibind_Skeletal_Transform12_UniformBlock;
876         /// uniform block indices
877         int ubiloc_Skeletal_Transform12_UniformBlock;
878 }
879 r_glsl_permutation_t;
880
881 #define SHADERPERMUTATION_HASHSIZE 256
882
883
884 // non-degradable "lightweight" shader parameters to keep the permutations simpler
885 // these can NOT degrade! only use for simple stuff
886 enum
887 {
888         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
889         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
890         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
891         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
892         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
893         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
894         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
895         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
896         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
897         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
898         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
899         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
900         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
901         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
902 };
903 #define SHADERSTATICPARMS_COUNT 14
904
905 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
906 static int shaderstaticparms_count = 0;
907
908 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
909 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
910
911 extern qboolean r_shadow_shadowmapsampler;
912 extern int r_shadow_shadowmappcf;
913 qboolean R_CompileShader_CheckStaticParms(void)
914 {
915         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
916         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
917         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
918
919         // detect all
920         if (r_glsl_saturation_redcompensate.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
922         if (r_glsl_vertextextureblend_usebothalphas.integer)
923                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
924         if (r_shadow_glossexact.integer)
925                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
926         if (r_glsl_postprocess.integer)
927         {
928                 if (r_glsl_postprocess_uservec1_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
930                 if (r_glsl_postprocess_uservec2_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
932                 if (r_glsl_postprocess_uservec3_enable.integer)
933                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
934                 if (r_glsl_postprocess_uservec4_enable.integer)
935                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
936         }
937         if (r_fxaa.integer)
938                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
939         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
940                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
941
942         if (r_shadow_shadowmapsampler)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
944         if (r_shadow_shadowmappcf > 1)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
946         else if (r_shadow_shadowmappcf)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
948         if (r_celshading.integer)
949                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
950         if (r_celoutlines.integer)
951                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
952
953         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
954 }
955
956 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
957         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
958                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
959         else \
960                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
961 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
962 {
963         shaderstaticparms_count = 0;
964
965         // emit all
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
976         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
977         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
978         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
979         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
980 }
981
982 /// information about each possible shader permutation
983 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
984 /// currently selected permutation
985 r_glsl_permutation_t *r_glsl_permutation;
986 /// storage for permutations linked in the hash table
987 memexpandablearray_t r_glsl_permutationarray;
988
989 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
990 {
991         //unsigned int hashdepth = 0;
992         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
993         r_glsl_permutation_t *p;
994         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
995         {
996                 if (p->mode == mode && p->permutation == permutation)
997                 {
998                         //if (hashdepth > 10)
999                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1000                         return p;
1001                 }
1002                 //hashdepth++;
1003         }
1004         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1005         p->mode = mode;
1006         p->permutation = permutation;
1007         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1008         r_glsl_permutationhash[mode][hashindex] = p;
1009         //if (hashdepth > 10)
1010         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1011         return p;
1012 }
1013
1014 static char *R_ShaderStrCat(const char **strings)
1015 {
1016         char *string, *s;
1017         const char **p = strings;
1018         const char *t;
1019         size_t len = 0;
1020         for (p = strings;(t = *p);p++)
1021                 len += strlen(t);
1022         len++;
1023         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1024         len = 0;
1025         for (p = strings;(t = *p);p++)
1026         {
1027                 len = strlen(t);
1028                 memcpy(s, t, len);
1029                 s += len;
1030         }
1031         *s = 0;
1032         return string;
1033 }
1034
1035 static char *R_ShaderStrCat(const char **strings);
1036 static void R_InitShaderModeInfo(void)
1037 {
1038         int i, language;
1039         shadermodeinfo_t *modeinfo;
1040         // 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)
1041         for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1042         {
1043                 for (i = 0; i < SHADERMODE_COUNT; i++)
1044                 {
1045                         char filename[MAX_QPATH];
1046                         modeinfo = &shadermodeinfo[language][i];
1047                         modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1048                         modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1049                         dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1050                         modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1051                 }
1052         }
1053 }
1054
1055 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1056 {
1057         char *shaderstring;
1058         // if the mode has no filename we have to return the builtin string
1059         if (builtinonly || !modeinfo->filename)
1060                 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1061         // note that FS_LoadFile appends a 0 byte to make it a valid string
1062         shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1063         if (shaderstring)
1064         {
1065                 if (printfromdisknotice)
1066                         Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1067                 return shaderstring;
1068         }
1069         // fall back to builtinstring
1070         return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071 }
1072
1073 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1074 {
1075         int i;
1076         int ubibind;
1077         int sampler;
1078         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1079         char *sourcestring;
1080         char permutationname[256];
1081         int vertstrings_count = 0;
1082         int geomstrings_count = 0;
1083         int fragstrings_count = 0;
1084         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1086         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1087
1088         if (p->compiled)
1089                 return;
1090         p->compiled = true;
1091         p->program = 0;
1092
1093         permutationname[0] = 0;
1094         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1095
1096         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1097
1098         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1099         if(vid.support.glshaderversion >= 140)
1100         {
1101                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1102                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1103                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1104                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1105                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1106                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1107         }
1108         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1109         else if(vid.support.glshaderversion >= 130)
1110         {
1111                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1112                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1113                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1114                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1115                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1116                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1117         }
1118
1119         // the first pretext is which type of shader to compile as
1120         // (later these will all be bound together as a program object)
1121         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1122         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1123         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1124
1125         // the second pretext is the mode (for example a light source)
1126         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1127         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1128         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1129         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1130
1131         // now add all the permutation pretexts
1132         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1133         {
1134                 if (permutation & (1<<i))
1135                 {
1136                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1137                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1138                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1139                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1140                 }
1141                 else
1142                 {
1143                         // keep line numbers correct
1144                         vertstrings_list[vertstrings_count++] = "\n";
1145                         geomstrings_list[geomstrings_count++] = "\n";
1146                         fragstrings_list[fragstrings_count++] = "\n";
1147                 }
1148         }
1149
1150         // add static parms
1151         R_CompileShader_AddStaticParms(mode, permutation);
1152         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153         vertstrings_count += shaderstaticparms_count;
1154         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1155         geomstrings_count += shaderstaticparms_count;
1156         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1157         fragstrings_count += shaderstaticparms_count;
1158
1159         // now append the shader text itself
1160         vertstrings_list[vertstrings_count++] = sourcestring;
1161         geomstrings_list[geomstrings_count++] = sourcestring;
1162         fragstrings_list[fragstrings_count++] = sourcestring;
1163
1164         // compile the shader program
1165         if (vertstrings_count + geomstrings_count + fragstrings_count)
1166                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1167         if (p->program)
1168         {
1169                 CHECKGLERROR
1170                 qglUseProgram(p->program);CHECKGLERROR
1171                 // look up all the uniform variable names we care about, so we don't
1172                 // have to look them up every time we set them
1173
1174 #if 0
1175                 // debugging aid
1176                 {
1177                         GLint activeuniformindex = 0;
1178                         GLint numactiveuniforms = 0;
1179                         char uniformname[128];
1180                         GLsizei uniformnamelength = 0;
1181                         GLint uniformsize = 0;
1182                         GLenum uniformtype = 0;
1183                         memset(uniformname, 0, sizeof(uniformname));
1184                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1185                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1186                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1187                         {
1188                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1189                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1190                         }
1191                 }
1192 #endif
1193
1194                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1195                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1196                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1197                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1198                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1199                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1200                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1201                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1202                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1203                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1204                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1205                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1206                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1207                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1208                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1209                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1210                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1211                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1212                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1213                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1214                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1215                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1216                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1217                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1218                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1219                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1220                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1221                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1222                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1223                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1224                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1225                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1226                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1227                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1228                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1229                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1230                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1231                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1232                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1233                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1234                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1235                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1236                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1237                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1238                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1239                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1240                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1241                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1242                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1243                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1244                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1245                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1246                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1247                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1248                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1249                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1250                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1251                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1252                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1253                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1254                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1255                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1256                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1257                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1258                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1259                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1260                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1261                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1262                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1263                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1264                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1265                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1266                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1267                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1268                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1269                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1270                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1271                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1272                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1273                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1274                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1275                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1276                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1277                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1278                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1279                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1280                 // initialize the samplers to refer to the texture units we use
1281                 p->tex_Texture_First = -1;
1282                 p->tex_Texture_Second = -1;
1283                 p->tex_Texture_GammaRamps = -1;
1284                 p->tex_Texture_Normal = -1;
1285                 p->tex_Texture_Color = -1;
1286                 p->tex_Texture_Gloss = -1;
1287                 p->tex_Texture_Glow = -1;
1288                 p->tex_Texture_SecondaryNormal = -1;
1289                 p->tex_Texture_SecondaryColor = -1;
1290                 p->tex_Texture_SecondaryGloss = -1;
1291                 p->tex_Texture_SecondaryGlow = -1;
1292                 p->tex_Texture_Pants = -1;
1293                 p->tex_Texture_Shirt = -1;
1294                 p->tex_Texture_FogHeightTexture = -1;
1295                 p->tex_Texture_FogMask = -1;
1296                 p->tex_Texture_Lightmap = -1;
1297                 p->tex_Texture_Deluxemap = -1;
1298                 p->tex_Texture_Attenuation = -1;
1299                 p->tex_Texture_Cube = -1;
1300                 p->tex_Texture_Refraction = -1;
1301                 p->tex_Texture_Reflection = -1;
1302                 p->tex_Texture_ShadowMap2D = -1;
1303                 p->tex_Texture_CubeProjection = -1;
1304                 p->tex_Texture_ScreenNormalMap = -1;
1305                 p->tex_Texture_ScreenDiffuse = -1;
1306                 p->tex_Texture_ScreenSpecular = -1;
1307                 p->tex_Texture_ReflectMask = -1;
1308                 p->tex_Texture_ReflectCube = -1;
1309                 p->tex_Texture_BounceGrid = -1;
1310                 // bind the texture samplers in use
1311                 sampler = 0;
1312                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1313                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1314                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1315                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1316                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1317                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1318                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1319                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1320                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1321                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1322                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1323                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1324                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1325                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1326                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1327                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1328                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1329                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1330                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1331                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1332                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1333                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1334                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1335                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1336                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1337                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1338                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1339                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1340                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1341                 // get the uniform block indices so we can bind them
1342 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1343                 if (vid.support.arb_uniform_buffer_object)
1344                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1345                 else
1346 #endif
1347                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1348                 // clear the uniform block bindings
1349                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1350                 // bind the uniform blocks in use
1351                 ubibind = 0;
1352 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1353                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1354 #endif
1355                 // we're done compiling and setting up the shader, at least until it is used
1356                 CHECKGLERROR
1357                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1358         }
1359         else
1360                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1361
1362         // free the strings
1363         if (sourcestring)
1364                 Mem_Free(sourcestring);
1365 }
1366
1367 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1368 {
1369         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1370         if (r_glsl_permutation != perm)
1371         {
1372                 r_glsl_permutation = perm;
1373                 if (!r_glsl_permutation->program)
1374                 {
1375                         if (!r_glsl_permutation->compiled)
1376                         {
1377                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1378                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1379                         }
1380                         if (!r_glsl_permutation->program)
1381                         {
1382                                 // remove features until we find a valid permutation
1383                                 int i;
1384                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1385                                 {
1386                                         // reduce i more quickly whenever it would not remove any bits
1387                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1388                                         if (!(permutation & j))
1389                                                 continue;
1390                                         permutation -= j;
1391                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1392                                         if (!r_glsl_permutation->compiled)
1393                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1394                                         if (r_glsl_permutation->program)
1395                                                 break;
1396                                 }
1397                                 if (i >= SHADERPERMUTATION_COUNT)
1398                                 {
1399                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1400                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401                                         qglUseProgram(0);CHECKGLERROR
1402                                         return; // no bit left to clear, entire mode is broken
1403                                 }
1404                         }
1405                 }
1406                 CHECKGLERROR
1407                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1408         }
1409         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1410         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1411         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1412         CHECKGLERROR
1413 }
1414
1415 #ifdef SUPPORTD3D
1416
1417 #ifdef SUPPORTD3D
1418 #include <d3d9.h>
1419 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1420 extern D3DCAPS9 vid_d3d9caps;
1421 #endif
1422
1423 struct r_hlsl_permutation_s;
1424 typedef struct r_hlsl_permutation_s
1425 {
1426         /// hash lookup data
1427         struct r_hlsl_permutation_s *hashnext;
1428         unsigned int mode;
1429         unsigned int permutation;
1430
1431         /// indicates if we have tried compiling this permutation already
1432         qboolean compiled;
1433         /// NULL if compilation failed
1434         IDirect3DVertexShader9 *vertexshader;
1435         IDirect3DPixelShader9 *pixelshader;
1436 }
1437 r_hlsl_permutation_t;
1438
1439 typedef enum D3DVSREGISTER_e
1440 {
1441         D3DVSREGISTER_TexMatrix = 0, // float4x4
1442         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1443         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1444         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1445         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1446         D3DVSREGISTER_ModelToLight = 20, // float4x4
1447         D3DVSREGISTER_EyePosition = 24,
1448         D3DVSREGISTER_FogPlane = 25,
1449         D3DVSREGISTER_LightDir = 26,
1450         D3DVSREGISTER_LightPosition = 27,
1451 }
1452 D3DVSREGISTER_t;
1453
1454 typedef enum D3DPSREGISTER_e
1455 {
1456         D3DPSREGISTER_Alpha = 0,
1457         D3DPSREGISTER_BloomBlur_Parameters = 1,
1458         D3DPSREGISTER_ClientTime = 2,
1459         D3DPSREGISTER_Color_Ambient = 3,
1460         D3DPSREGISTER_Color_Diffuse = 4,
1461         D3DPSREGISTER_Color_Specular = 5,
1462         D3DPSREGISTER_Color_Glow = 6,
1463         D3DPSREGISTER_Color_Pants = 7,
1464         D3DPSREGISTER_Color_Shirt = 8,
1465         D3DPSREGISTER_DeferredColor_Ambient = 9,
1466         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1467         D3DPSREGISTER_DeferredColor_Specular = 11,
1468         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1469         D3DPSREGISTER_DeferredMod_Specular = 13,
1470         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1471         D3DPSREGISTER_EyePosition = 15, // unused
1472         D3DPSREGISTER_FogColor = 16,
1473         D3DPSREGISTER_FogHeightFade = 17,
1474         D3DPSREGISTER_FogPlane = 18,
1475         D3DPSREGISTER_FogPlaneViewDist = 19,
1476         D3DPSREGISTER_FogRangeRecip = 20,
1477         D3DPSREGISTER_LightColor = 21,
1478         D3DPSREGISTER_LightDir = 22, // unused
1479         D3DPSREGISTER_LightPosition = 23,
1480         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1481         D3DPSREGISTER_PixelSize = 25,
1482         D3DPSREGISTER_ReflectColor = 26,
1483         D3DPSREGISTER_ReflectFactor = 27,
1484         D3DPSREGISTER_ReflectOffset = 28,
1485         D3DPSREGISTER_RefractColor = 29,
1486         D3DPSREGISTER_Saturation = 30,
1487         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1488         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1489         D3DPSREGISTER_ScreenToDepth = 33,
1490         D3DPSREGISTER_ShadowMap_Parameters = 34,
1491         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1492         D3DPSREGISTER_SpecularPower = 36,
1493         D3DPSREGISTER_UserVec1 = 37,
1494         D3DPSREGISTER_UserVec2 = 38,
1495         D3DPSREGISTER_UserVec3 = 39,
1496         D3DPSREGISTER_UserVec4 = 40,
1497         D3DPSREGISTER_ViewTintColor = 41,
1498         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1499         D3DPSREGISTER_BloomColorSubtract = 43,
1500         D3DPSREGISTER_ViewToLight = 44, // float4x4
1501         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1502         D3DPSREGISTER_NormalmapScrollBlend = 52,
1503         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1504         D3DPSREGISTER_OffsetMapping_Bias = 54,
1505         // next at 54
1506 }
1507 D3DPSREGISTER_t;
1508
1509 /// information about each possible shader permutation
1510 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1511 /// currently selected permutation
1512 r_hlsl_permutation_t *r_hlsl_permutation;
1513 /// storage for permutations linked in the hash table
1514 memexpandablearray_t r_hlsl_permutationarray;
1515
1516 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1517 {
1518         //unsigned int hashdepth = 0;
1519         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1520         r_hlsl_permutation_t *p;
1521         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1522         {
1523                 if (p->mode == mode && p->permutation == permutation)
1524                 {
1525                         //if (hashdepth > 10)
1526                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1527                         return p;
1528                 }
1529                 //hashdepth++;
1530         }
1531         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1532         p->mode = mode;
1533         p->permutation = permutation;
1534         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1535         r_hlsl_permutationhash[mode][hashindex] = p;
1536         //if (hashdepth > 10)
1537         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1538         return p;
1539 }
1540
1541 #include <d3dx9.h>
1542 //#include <d3dx9shader.h>
1543 //#include <d3dx9mesh.h>
1544
1545 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1546 {
1547         DWORD *vsbin = NULL;
1548         DWORD *psbin = NULL;
1549         fs_offset_t vsbinsize;
1550         fs_offset_t psbinsize;
1551 //      IDirect3DVertexShader9 *vs = NULL;
1552 //      IDirect3DPixelShader9 *ps = NULL;
1553         ID3DXBuffer *vslog = NULL;
1554         ID3DXBuffer *vsbuffer = NULL;
1555         ID3DXConstantTable *vsconstanttable = NULL;
1556         ID3DXBuffer *pslog = NULL;
1557         ID3DXBuffer *psbuffer = NULL;
1558         ID3DXConstantTable *psconstanttable = NULL;
1559         int vsresult = 0;
1560         int psresult = 0;
1561         char temp[MAX_INPUTLINE];
1562         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1563         char vabuf[1024];
1564         qboolean debugshader = gl_paranoid.integer != 0;
1565         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1566         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1567         if (!debugshader)
1568         {
1569                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1570                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1571         }
1572         if ((!vsbin && vertstring) || (!psbin && fragstring))
1573         {
1574                 const char* dllnames_d3dx9 [] =
1575                 {
1576                         "d3dx9_43.dll",
1577                         "d3dx9_42.dll",
1578                         "d3dx9_41.dll",
1579                         "d3dx9_40.dll",
1580                         "d3dx9_39.dll",
1581                         "d3dx9_38.dll",
1582                         "d3dx9_37.dll",
1583                         "d3dx9_36.dll",
1584                         "d3dx9_35.dll",
1585                         "d3dx9_34.dll",
1586                         "d3dx9_33.dll",
1587                         "d3dx9_32.dll",
1588                         "d3dx9_31.dll",
1589                         "d3dx9_30.dll",
1590                         "d3dx9_29.dll",
1591                         "d3dx9_28.dll",
1592                         "d3dx9_27.dll",
1593                         "d3dx9_26.dll",
1594                         "d3dx9_25.dll",
1595                         "d3dx9_24.dll",
1596                         NULL
1597                 };
1598                 dllhandle_t d3dx9_dll = NULL;
1599                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1600                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1601                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1602                 dllfunction_t d3dx9_dllfuncs[] =
1603                 {
1604                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1605                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1606                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1607                         {NULL, NULL}
1608                 };
1609                 // 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...
1610 #ifndef ID3DXBuffer_GetBufferPointer
1611 #if !defined(__cplusplus) || defined(CINTERFACE)
1612 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1613 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1614 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1615 #else
1616 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1617 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1618 #define ID3DXBuffer_Release(p)            (p)->Release()
1619 #endif
1620 #endif
1621                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1622                 {
1623                         DWORD shaderflags = 0;
1624                         if (debugshader)
1625                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1626                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1627                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1628                         if (vertstring && vertstring[0])
1629                         {
1630                                 if (debugshader)
1631                                 {
1632                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1633                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1634                                 }
1635                                 else
1636                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1637                                 if (vsbuffer)
1638                                 {
1639                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1640                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1641                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1642                                         ID3DXBuffer_Release(vsbuffer);
1643                                 }
1644                                 if (vslog)
1645                                 {
1646                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1647                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1648                                         ID3DXBuffer_Release(vslog);
1649                                 }
1650                         }
1651                         if (fragstring && fragstring[0])
1652                         {
1653                                 if (debugshader)
1654                                 {
1655                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1656                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1657                                 }
1658                                 else
1659                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1660                                 if (psbuffer)
1661                                 {
1662                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1663                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1664                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1665                                         ID3DXBuffer_Release(psbuffer);
1666                                 }
1667                                 if (pslog)
1668                                 {
1669                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1670                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1671                                         ID3DXBuffer_Release(pslog);
1672                                 }
1673                         }
1674                         Sys_UnloadLibrary(&d3dx9_dll);
1675                 }
1676                 else
1677                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1678         }
1679         if (vsbin && psbin)
1680         {
1681                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1682                 if (FAILED(vsresult))
1683                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1684                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1685                 if (FAILED(psresult))
1686                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1687         }
1688         // free the shader data
1689         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1690         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1691 }
1692
1693 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1694 {
1695         int i;
1696         shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1697         int vertstring_length = 0;
1698         int geomstring_length = 0;
1699         int fragstring_length = 0;
1700         char *t;
1701         char *sourcestring;
1702         char *vertstring, *geomstring, *fragstring;
1703         char permutationname[256];
1704         char cachename[256];
1705         int vertstrings_count = 0;
1706         int geomstrings_count = 0;
1707         int fragstrings_count = 0;
1708         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1709         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1710         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1711
1712         if (p->compiled)
1713                 return;
1714         p->compiled = true;
1715         p->vertexshader = NULL;
1716         p->pixelshader = NULL;
1717
1718         permutationname[0] = 0;
1719         cachename[0] = 0;
1720         sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1721
1722         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1723         strlcat(cachename, "hlsl/", sizeof(cachename));
1724
1725         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1726         vertstrings_count = 0;
1727         geomstrings_count = 0;
1728         fragstrings_count = 0;
1729         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1730         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1731         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1732
1733         // the first pretext is which type of shader to compile as
1734         // (later these will all be bound together as a program object)
1735         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1736         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1737         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1738
1739         // the second pretext is the mode (for example a light source)
1740         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1741         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1742         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1743         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1744         strlcat(cachename, modeinfo->name, sizeof(cachename));
1745
1746         // now add all the permutation pretexts
1747         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1748         {
1749                 if (permutation & (1<<i))
1750                 {
1751                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1752                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1753                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1754                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1755                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1756                 }
1757                 else
1758                 {
1759                         // keep line numbers correct
1760                         vertstrings_list[vertstrings_count++] = "\n";
1761                         geomstrings_list[geomstrings_count++] = "\n";
1762                         fragstrings_list[fragstrings_count++] = "\n";
1763                 }
1764         }
1765
1766         // add static parms
1767         R_CompileShader_AddStaticParms(mode, permutation);
1768         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769         vertstrings_count += shaderstaticparms_count;
1770         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1771         geomstrings_count += shaderstaticparms_count;
1772         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1773         fragstrings_count += shaderstaticparms_count;
1774
1775         // replace spaces in the cachename with _ characters
1776         for (i = 0;cachename[i];i++)
1777                 if (cachename[i] == ' ')
1778                         cachename[i] = '_';
1779
1780         // now append the shader text itself
1781         vertstrings_list[vertstrings_count++] = sourcestring;
1782         geomstrings_list[geomstrings_count++] = sourcestring;
1783         fragstrings_list[fragstrings_count++] = sourcestring;
1784
1785         vertstring_length = 0;
1786         for (i = 0;i < vertstrings_count;i++)
1787                 vertstring_length += (int)strlen(vertstrings_list[i]);
1788         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1789         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1790                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1791
1792         geomstring_length = 0;
1793         for (i = 0;i < geomstrings_count;i++)
1794                 geomstring_length += (int)strlen(geomstrings_list[i]);
1795         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1796         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1797                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1798
1799         fragstring_length = 0;
1800         for (i = 0;i < fragstrings_count;i++)
1801                 fragstring_length += (int)strlen(fragstrings_list[i]);
1802         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1803         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1804                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1805
1806         // try to load the cached shader, or generate one
1807         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1808
1809         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1810                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1811         else
1812                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1813
1814         // free the strings
1815         if (vertstring)
1816                 Mem_Free(vertstring);
1817         if (geomstring)
1818                 Mem_Free(geomstring);
1819         if (fragstring)
1820                 Mem_Free(fragstring);
1821         if (sourcestring)
1822                 Mem_Free(sourcestring);
1823 }
1824
1825 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1826 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1827 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);}
1828 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);}
1829 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);}
1830 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);}
1831
1832 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1833 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1834 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);}
1835 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);}
1836 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);}
1837 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);}
1838
1839 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1840 {
1841         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1842         if (r_hlsl_permutation != perm)
1843         {
1844                 r_hlsl_permutation = perm;
1845                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1846                 {
1847                         if (!r_hlsl_permutation->compiled)
1848                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1849                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1850                         {
1851                                 // remove features until we find a valid permutation
1852                                 int i;
1853                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1854                                 {
1855                                         // reduce i more quickly whenever it would not remove any bits
1856                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1857                                         if (!(permutation & j))
1858                                                 continue;
1859                                         permutation -= j;
1860                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1861                                         if (!r_hlsl_permutation->compiled)
1862                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1863                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1864                                                 break;
1865                                 }
1866                                 if (i >= SHADERPERMUTATION_COUNT)
1867                                 {
1868                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1869                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870                                         return; // no bit left to clear, entire mode is broken
1871                                 }
1872                         }
1873                 }
1874                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1875                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1876         }
1877         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1878         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1879         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1880 }
1881 #endif
1882
1883 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1884 {
1885         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1886         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1887         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1888         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1889 }
1890
1891 void R_GLSL_Restart_f(void)
1892 {
1893         unsigned int i, limit;
1894         switch(vid.renderpath)
1895         {
1896         case RENDERPATH_D3D9:
1897 #ifdef SUPPORTD3D
1898                 {
1899                         r_hlsl_permutation_t *p;
1900                         r_hlsl_permutation = NULL;
1901                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1902                         for (i = 0;i < limit;i++)
1903                         {
1904                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1905                                 {
1906                                         if (p->vertexshader)
1907                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1908                                         if (p->pixelshader)
1909                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1910                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1911                                 }
1912                         }
1913                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1914                 }
1915 #endif
1916                 break;
1917         case RENDERPATH_D3D10:
1918                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1919                 break;
1920         case RENDERPATH_D3D11:
1921                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922                 break;
1923         case RENDERPATH_GL20:
1924         case RENDERPATH_GLES2:
1925                 {
1926                         r_glsl_permutation_t *p;
1927                         r_glsl_permutation = NULL;
1928                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1929                         for (i = 0;i < limit;i++)
1930                         {
1931                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1932                                 {
1933                                         GL_Backend_FreeProgram(p->program);
1934                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1935                                 }
1936                         }
1937                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1938                 }
1939                 break;
1940         case RENDERPATH_GL11:
1941         case RENDERPATH_GL13:
1942         case RENDERPATH_GLES1:
1943                 break;
1944         case RENDERPATH_SOFT:
1945                 break;
1946         }
1947 }
1948
1949 static void R_GLSL_DumpShader_f(void)
1950 {
1951         int i, language, mode, dupe;
1952         char *text;
1953         shadermodeinfo_t *modeinfo;
1954         qfile_t *file;
1955
1956         for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1957         {
1958                 modeinfo = shadermodeinfo[language];
1959                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1960                 {
1961                         // don't dump the same file multiple times (most or all shaders come from the same file)
1962                         for (dupe = mode - 1;dupe >= 0;dupe--)
1963                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1964                                         break;
1965                         if (dupe >= 0)
1966                                 continue;
1967                         text = modeinfo[mode].builtinstring;
1968                         if (!text)
1969                                 continue;
1970                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1971                         if (file)
1972                         {
1973                                 FS_Print(file, "/* The engine may define the following macros:\n");
1974                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1975                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1976                                         FS_Print(file, modeinfo[i].pretext);
1977                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1978                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1979                                 FS_Print(file, "*/\n");
1980                                 FS_Print(file, text);
1981                                 FS_Close(file);
1982                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1983                         }
1984                         else
1985                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1986                 }
1987         }
1988 }
1989
1990 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1991 {
1992         unsigned int permutation = 0;
1993         if (r_trippy.integer && !notrippy)
1994                 permutation |= SHADERPERMUTATION_TRIPPY;
1995         permutation |= SHADERPERMUTATION_VIEWTINT;
1996         if (first)
1997                 permutation |= SHADERPERMUTATION_DIFFUSE;
1998         if (second)
1999                 permutation |= SHADERPERMUTATION_SPECULAR;
2000         if (texturemode == GL_MODULATE)
2001                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2002         else if (texturemode == GL_ADD)
2003                 permutation |= SHADERPERMUTATION_GLOW;
2004         else if (texturemode == GL_DECAL)
2005                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2006         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2007                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2008         if (suppresstexalpha)
2009                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2010         if (!second)
2011                 texturemode = GL_MODULATE;
2012         if (vid.allowalphatocoverage)
2013                 GL_AlphaToCoverage(false);
2014         switch (vid.renderpath)
2015         {
2016         case RENDERPATH_D3D9:
2017 #ifdef SUPPORTD3D
2018                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2019                 R_Mesh_TexBind(GL20TU_FIRST , first );
2020                 R_Mesh_TexBind(GL20TU_SECOND, second);
2021                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2022                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2023 #endif
2024                 break;
2025         case RENDERPATH_D3D10:
2026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                 break;
2028         case RENDERPATH_D3D11:
2029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030                 break;
2031         case RENDERPATH_GL20:
2032         case RENDERPATH_GLES2:
2033                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2034                 if (r_glsl_permutation->tex_Texture_First >= 0)
2035                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2036                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2037                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2038                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2039                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2040                 break;
2041         case RENDERPATH_GL13:
2042         case RENDERPATH_GLES1:
2043                 R_Mesh_TexBind(0, first );
2044                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2045                 R_Mesh_TexMatrix(0, NULL);
2046                 R_Mesh_TexBind(1, second);
2047                 if (second)
2048                 {
2049                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2050                         R_Mesh_TexMatrix(1, NULL);
2051                 }
2052                 break;
2053         case RENDERPATH_GL11:
2054                 R_Mesh_TexBind(0, first );
2055                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2056                 R_Mesh_TexMatrix(0, NULL);
2057                 break;
2058         case RENDERPATH_SOFT:
2059                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2060                 R_Mesh_TexBind(GL20TU_FIRST , first );
2061                 R_Mesh_TexBind(GL20TU_SECOND, second);
2062                 break;
2063         }
2064 }
2065
2066 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2067 {
2068         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2069 }
2070
2071 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2072 {
2073         unsigned int permutation = 0;
2074         if (r_trippy.integer && !notrippy)
2075                 permutation |= SHADERPERMUTATION_TRIPPY;
2076         if (depthrgb)
2077                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2078         if (skeletal)
2079                 permutation |= SHADERPERMUTATION_SKELETAL;
2080
2081         if (vid.allowalphatocoverage)
2082                 GL_AlphaToCoverage(false);
2083         switch (vid.renderpath)
2084         {
2085         case RENDERPATH_D3D9:
2086 #ifdef SUPPORTD3D
2087                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2088 #endif
2089                 break;
2090         case RENDERPATH_D3D10:
2091                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2092                 break;
2093         case RENDERPATH_D3D11:
2094                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2095                 break;
2096         case RENDERPATH_GL20:
2097         case RENDERPATH_GLES2:
2098                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2099 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2100                 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);
2101 #endif
2102                 break;
2103         case RENDERPATH_GL13:
2104         case RENDERPATH_GLES1:
2105                 R_Mesh_TexBind(0, 0);
2106                 R_Mesh_TexBind(1, 0);
2107                 break;
2108         case RENDERPATH_GL11:
2109                 R_Mesh_TexBind(0, 0);
2110                 break;
2111         case RENDERPATH_SOFT:
2112                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2113                 break;
2114         }
2115 }
2116
2117 extern qboolean r_shadow_usingdeferredprepass;
2118 extern rtexture_t *r_shadow_attenuationgradienttexture;
2119 extern rtexture_t *r_shadow_attenuation2dtexture;
2120 extern rtexture_t *r_shadow_attenuation3dtexture;
2121 extern qboolean r_shadow_usingshadowmap2d;
2122 extern qboolean r_shadow_usingshadowmaportho;
2123 extern float r_shadow_modelshadowmap_texturescale[4];
2124 extern float r_shadow_modelshadowmap_parameters[4];
2125 extern float r_shadow_lightshadowmap_texturescale[4];
2126 extern float r_shadow_lightshadowmap_parameters[4];
2127 extern qboolean r_shadow_shadowmapvsdct;
2128 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2129 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2130 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2131 extern matrix4x4_t r_shadow_shadowmapmatrix;
2132 extern int r_shadow_prepass_width;
2133 extern int r_shadow_prepass_height;
2134 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2135 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2136 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2137 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2138
2139 #define BLENDFUNC_ALLOWS_COLORMOD      1
2140 #define BLENDFUNC_ALLOWS_FOG           2
2141 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2142 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2143 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2144 static int R_BlendFuncFlags(int src, int dst)
2145 {
2146         int r = 0;
2147
2148         // a blendfunc allows colormod if:
2149         // a) it can never keep the destination pixel invariant, or
2150         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2151         // this is to prevent unintended side effects from colormod
2152
2153         // a blendfunc allows fog if:
2154         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2155         // this is to prevent unintended side effects from fog
2156
2157         // these checks are the output of fogeval.pl
2158
2159         r |= BLENDFUNC_ALLOWS_COLORMOD;
2160         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2161         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2162         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2164         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2168         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2169         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2170         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2171         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2174         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2175         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2178         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2179         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2180         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181
2182         return r;
2183 }
2184
2185 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)
2186 {
2187         // select a permutation of the lighting shader appropriate to this
2188         // combination of texture, entity, light source, and fogging, only use the
2189         // minimum features necessary to avoid wasting rendering time in the
2190         // fragment shader on features that are not being used
2191         unsigned int permutation = 0;
2192         unsigned int mode = 0;
2193         int blendfuncflags;
2194         static float dummy_colormod[3] = {1, 1, 1};
2195         float *colormod = rsurface.colormod;
2196         float m16f[16];
2197         matrix4x4_t tempmatrix;
2198         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2199         if (r_trippy.integer && !notrippy)
2200                 permutation |= SHADERPERMUTATION_TRIPPY;
2201         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2202                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2203         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2204                 permutation |= SHADERPERMUTATION_OCCLUDE;
2205         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2206                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207         if (rsurfacepass == RSURFPASS_BACKGROUND)
2208         {
2209                 // distorted background
2210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2211                 {
2212                         mode = SHADERMODE_WATER;
2213                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2216                         {
2217                                 // this is the right thing to do for wateralpha
2218                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2219                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2220                         }
2221                         else
2222                         {
2223                                 // this is the right thing to do for entity alpha
2224                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2226                         }
2227                 }
2228                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2229                 {
2230                         mode = SHADERMODE_REFRACTION;
2231                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2235                 }
2236                 else
2237                 {
2238                         mode = SHADERMODE_GENERIC;
2239                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2242                 }
2243                 if (vid.allowalphatocoverage)
2244                         GL_AlphaToCoverage(false);
2245         }
2246         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2247         {
2248                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2249                 {
2250                         switch(rsurface.texture->offsetmapping)
2251                         {
2252                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255                         case OFFSETMAPPING_OFF: break;
2256                         }
2257                 }
2258                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260                 // normalmap (deferred prepass), may use alpha test on diffuse
2261                 mode = SHADERMODE_DEFERREDGEOMETRY;
2262                 GL_BlendFunc(GL_ONE, GL_ZERO);
2263                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264                 if (vid.allowalphatocoverage)
2265                         GL_AlphaToCoverage(false);
2266         }
2267         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2268         {
2269                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2270                 {
2271                         switch(rsurface.texture->offsetmapping)
2272                         {
2273                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276                         case OFFSETMAPPING_OFF: break;
2277                         }
2278                 }
2279                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2283                 // light source
2284                 mode = SHADERMODE_LIGHTSOURCE;
2285                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2287                 if (diffusescale > 0)
2288                         permutation |= SHADERPERMUTATION_DIFFUSE;
2289                 if (specularscale > 0)
2290                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291                 if (r_refdef.fogenabled)
2292                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293                 if (rsurface.texture->colormapping)
2294                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2295                 if (r_shadow_usingshadowmap2d)
2296                 {
2297                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298                         if(r_shadow_shadowmapvsdct)
2299                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2300
2301                         if (r_shadow_shadowmap2ddepthbuffer)
2302                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2303                 }
2304                 if (rsurface.texture->reflectmasktexture)
2305                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308                 if (vid.allowalphatocoverage)
2309                         GL_AlphaToCoverage(false);
2310         }
2311         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2312         {
2313                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2314                 {
2315                         switch(rsurface.texture->offsetmapping)
2316                         {
2317                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320                         case OFFSETMAPPING_OFF: break;
2321                         }
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327                 // unshaded geometry (fullbright or ambient model lighting)
2328                 mode = SHADERMODE_FLATCOLOR;
2329                 ambientscale = diffusescale = specularscale = 0;
2330                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331                         permutation |= SHADERPERMUTATION_GLOW;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmap2ddepthbuffer)
2342                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (rsurface.texture->reflectmasktexture)
2347                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350                 // when using alphatocoverage, we don't need alphakill
2351                 if (vid.allowalphatocoverage)
2352                 {
2353                         if (r_transparent_alphatocoverage.integer)
2354                         {
2355                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2356                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2357                         }
2358                         else
2359                                 GL_AlphaToCoverage(false);
2360                 }
2361         }
2362         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2363         {
2364                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2365                 {
2366                         switch(rsurface.texture->offsetmapping)
2367                         {
2368                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2369                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2370                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2371                         case OFFSETMAPPING_OFF: break;
2372                         }
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2375                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2377                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2378                 // directional model lighting
2379                 mode = SHADERMODE_LIGHTDIRECTION;
2380                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381                         permutation |= SHADERPERMUTATION_GLOW;
2382                 permutation |= SHADERPERMUTATION_DIFFUSE;
2383                 if (specularscale > 0)
2384                         permutation |= SHADERPERMUTATION_SPECULAR;
2385                 if (r_refdef.fogenabled)
2386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387                 if (rsurface.texture->colormapping)
2388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2389                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2390                 {
2391                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2393
2394                         if (r_shadow_shadowmap2ddepthbuffer)
2395                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2396                 }
2397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398                         permutation |= SHADERPERMUTATION_REFLECTION;
2399                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401                 if (rsurface.texture->reflectmasktexture)
2402                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2404                 {
2405                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2406                         if (r_shadow_bouncegrid_state.directional)
2407                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2408                 }
2409                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2410                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411                 // when using alphatocoverage, we don't need alphakill
2412                 if (vid.allowalphatocoverage)
2413                 {
2414                         if (r_transparent_alphatocoverage.integer)
2415                         {
2416                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2417                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2418                         }
2419                         else
2420                                 GL_AlphaToCoverage(false);
2421                 }
2422         }
2423         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2424         {
2425                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2426                 {
2427                         switch(rsurface.texture->offsetmapping)
2428                         {
2429                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2430                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2431                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432                         case OFFSETMAPPING_OFF: break;
2433                         }
2434                 }
2435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2436                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2438                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2439                 // ambient model lighting
2440                 mode = SHADERMODE_LIGHTDIRECTION;
2441                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2442                         permutation |= SHADERPERMUTATION_GLOW;
2443                 if (r_refdef.fogenabled)
2444                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2445                 if (rsurface.texture->colormapping)
2446                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2447                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2448                 {
2449                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2450                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2451
2452                         if (r_shadow_shadowmap2ddepthbuffer)
2453                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2454                 }
2455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2456                         permutation |= SHADERPERMUTATION_REFLECTION;
2457                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2458                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2459                 if (rsurface.texture->reflectmasktexture)
2460                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2461                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2462                 {
2463                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2464                         if (r_shadow_bouncegrid_state.directional)
2465                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2466                 }
2467                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2468                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2469                 // when using alphatocoverage, we don't need alphakill
2470                 if (vid.allowalphatocoverage)
2471                 {
2472                         if (r_transparent_alphatocoverage.integer)
2473                         {
2474                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2475                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2476                         }
2477                         else
2478                                 GL_AlphaToCoverage(false);
2479                 }
2480         }
2481         else
2482         {
2483                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2484                 {
2485                         switch(rsurface.texture->offsetmapping)
2486                         {
2487                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2488                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2489                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2490                         case OFFSETMAPPING_OFF: break;
2491                         }
2492                 }
2493                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2494                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2495                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2496                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2497                 // lightmapped wall
2498                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2499                         permutation |= SHADERPERMUTATION_GLOW;
2500                 if (r_refdef.fogenabled)
2501                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2502                 if (rsurface.texture->colormapping)
2503                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2504                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2505                 {
2506                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2507                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2508
2509                         if (r_shadow_shadowmap2ddepthbuffer)
2510                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2511                 }
2512                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2513                         permutation |= SHADERPERMUTATION_REFLECTION;
2514                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2515                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2516                 if (rsurface.texture->reflectmasktexture)
2517                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2518                 if (FAKELIGHT_ENABLED)
2519                 {
2520                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2521                         mode = SHADERMODE_FAKELIGHT;
2522                         permutation |= SHADERPERMUTATION_DIFFUSE;
2523                         if (specularscale > 0)
2524                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2525                 }
2526                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2527                 {
2528                         // deluxemapping (light direction texture)
2529                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2530                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2531                         else
2532                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2533                         permutation |= SHADERPERMUTATION_DIFFUSE;
2534                         if (specularscale > 0)
2535                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2536                 }
2537                 else if (r_glsl_deluxemapping.integer >= 2)
2538                 {
2539                         // fake deluxemapping (uniform light direction in tangentspace)
2540                         if (rsurface.uselightmaptexture)
2541                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2542                         else
2543                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2544                         permutation |= SHADERPERMUTATION_DIFFUSE;
2545                         if (specularscale > 0)
2546                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2547                 }
2548                 else if (rsurface.uselightmaptexture)
2549                 {
2550                         // ordinary lightmapping (q1bsp, q3bsp)
2551                         mode = SHADERMODE_LIGHTMAP;
2552                 }
2553                 else
2554                 {
2555                         // ordinary vertex coloring (q3bsp)
2556                         mode = SHADERMODE_VERTEXCOLOR;
2557                 }
2558                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2559                 {
2560                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2561                         if (r_shadow_bouncegrid_state.directional)
2562                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2563                 }
2564                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2565                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2566                 // when using alphatocoverage, we don't need alphakill
2567                 if (vid.allowalphatocoverage)
2568                 {
2569                         if (r_transparent_alphatocoverage.integer)
2570                         {
2571                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2572                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2573                         }
2574                         else
2575                                 GL_AlphaToCoverage(false);
2576                 }
2577         }
2578         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2579                 colormod = dummy_colormod;
2580         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2581                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2582         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2583                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2584         switch(vid.renderpath)
2585         {
2586         case RENDERPATH_D3D9:
2587 #ifdef SUPPORTD3D
2588                 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);
2589                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2590                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2591                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2592                 if (mode == SHADERMODE_LIGHTSOURCE)
2593                 {
2594                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2595                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2596                 }
2597                 else
2598                 {
2599                         if (mode == SHADERMODE_LIGHTDIRECTION)
2600                         {
2601                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2602                         }
2603                 }
2604                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2605                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2606                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2607                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2608                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2609
2610                 if (mode == SHADERMODE_LIGHTSOURCE)
2611                 {
2612                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2613                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2617
2618                         // additive passes are only darkened by fog, not tinted
2619                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2620                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2621                 }
2622                 else
2623                 {
2624                         if (mode == SHADERMODE_FLATCOLOR)
2625                         {
2626                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2627                         }
2628                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2629                         {
2630                                 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]);
2631                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2632                                 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);
2633                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2634                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2635                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2637                         }
2638                         else
2639                         {
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2641                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2642                                 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);
2643                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2645                         }
2646                         // additive passes are only darkened by fog, not tinted
2647                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2649                         else
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651                         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);
2652                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2653                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2654                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2655                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2658                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659                         if (mode == SHADERMODE_WATER)
2660                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2661                 }
2662                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2663                 {
2664                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2665                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2666                 }
2667                 else
2668                 {
2669                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2670                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2671                 }
2672                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2673                 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));
2674                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2675                 if (rsurface.texture->pantstexture)
2676                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2677                 else
2678                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2679                 if (rsurface.texture->shirttexture)
2680                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2681                 else
2682                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2683                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2684                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2685                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2686                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2687                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2688                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2689                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2690                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2692                         );
2693                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2694                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2695                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2696                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2697
2698                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2699                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2700                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2701                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2702                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2703                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2704                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2705                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2706                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2707                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2708                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2709                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2710                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2711                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2712                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2715                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2716                 {
2717                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2718                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2719                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2720                 }
2721                 else
2722                 {
2723                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2724                 }
2725 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2726                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2727                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2728                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2729                 {
2730                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2731                         if (rsurface.rtlight)
2732                         {
2733                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2734                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2735                         }
2736                 }
2737 #endif
2738                 break;
2739         case RENDERPATH_D3D10:
2740                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2741                 break;
2742         case RENDERPATH_D3D11:
2743                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2744                 break;
2745         case RENDERPATH_GL20:
2746         case RENDERPATH_GLES2:
2747                 if (!vid.useinterleavedarrays)
2748                 {
2749                         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);
2750                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2751                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2752                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2753                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2754                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2755                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2756                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2757                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2758                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2759                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2760                 }
2761                 else
2762                 {
2763                         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);
2764                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2765                 }
2766                 // this has to be after RSurf_PrepareVerticesForBatch
2767                 if (rsurface.batchskeletaltransform3x4buffer)
2768                         permutation |= SHADERPERMUTATION_SKELETAL;
2769                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2770 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2771                 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);
2772 #endif
2773                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2774                 if (mode == SHADERMODE_LIGHTSOURCE)
2775                 {
2776                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2777                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2778                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2779                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2780                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2781                         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);
2782         
2783                         // additive passes are only darkened by fog, not tinted
2784                         if (r_glsl_permutation->loc_FogColor >= 0)
2785                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2786                         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);
2787                 }
2788                 else
2789                 {
2790                         if (mode == SHADERMODE_FLATCOLOR)
2791                         {
2792                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2793                         }
2794                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2795                         {
2796                                 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]);
2797                                 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]);
2798                                 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);
2799                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2800                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2801                                 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]);
2802                                 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]);
2803                         }
2804                         else
2805                         {
2806                                 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]);
2807                                 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]);
2808                                 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);
2809                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2810                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2811                         }
2812                         // additive passes are only darkened by fog, not tinted
2813                         if (r_glsl_permutation->loc_FogColor >= 0)
2814                         {
2815                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2816                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2817                                 else
2818                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2819                         }
2820                         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);
2821                         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]);
2822                         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]);
2823                         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]);
2824                         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]);
2825                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2826                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2827                         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);
2828                         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]);
2829                 }
2830                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2831                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2832                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2833                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2834                 {
2835                         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]);
2836                         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]);
2837                 }
2838                 else
2839                 {
2840                         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]);
2841                         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]);
2842                 }
2843
2844                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2845                 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));
2846                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2847                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2848                 {
2849                         if (rsurface.texture->pantstexture)
2850                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2851                         else
2852                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2853                 }
2854                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2855                 {
2856                         if (rsurface.texture->shirttexture)
2857                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2858                         else
2859                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2860                 }
2861                 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]);
2862                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2863                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2864                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2865                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2866                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2867                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2868                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2869                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2870                         );
2871                 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);
2872                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2873                 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]);
2874                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2875                 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);}
2876                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2877
2878                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2879                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2880                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2881                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2882                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2883                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2884                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2885                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2886                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2887                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2888                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2889                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2890                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2891                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2892                 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);
2893                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2894                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2895                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2896                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2897                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2898                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2899                 {
2900                         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);
2901                         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);
2902                         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);
2903                 }
2904                 else
2905                 {
2906                         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);
2907                 }
2908                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2909                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2910                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2911                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2912                 {
2913                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2914                         if (rsurface.rtlight)
2915                         {
2916                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2917                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2918                         }
2919                 }
2920                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2921                 CHECKGLERROR
2922                 break;
2923         case RENDERPATH_GL11:
2924         case RENDERPATH_GL13:
2925         case RENDERPATH_GLES1:
2926                 break;
2927         case RENDERPATH_SOFT:
2928                 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);
2929                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2930                 R_SetupShader_SetPermutationSoft(mode, permutation);
2931                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2932                 if (mode == SHADERMODE_LIGHTSOURCE)
2933                 {
2934                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2935                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2936                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2938                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2939                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2940         
2941                         // additive passes are only darkened by fog, not tinted
2942                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2943                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2944                 }
2945                 else
2946                 {
2947                         if (mode == SHADERMODE_FLATCOLOR)
2948                         {
2949                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2950                         }
2951                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2952                         {
2953                                 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]);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2955                                 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);
2956                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2957                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2958                                 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]);
2959                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2960                         }
2961                         else
2962                         {
2963                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2964                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2965                                 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);
2966                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2967                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2968                         }
2969                         // additive passes are only darkened by fog, not tinted
2970                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2971                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2972                         else
2973                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2974                         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);
2975                         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]);
2976                         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]);
2977                         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]);
2978                         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]);
2979                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2980                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2981                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2982                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2983                 }
2984                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2985                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2986                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2987                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2988                 {
2989                         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]);
2990                         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]);
2991                 }
2992                 else
2993                 {
2994                         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]);
2995                         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]);
2996                 }
2997
2998                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2999                 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));
3000                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3001                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3002                 {
3003                         if (rsurface.texture->pantstexture)
3004                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3005                         else
3006                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3007                 }
3008                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3009                 {
3010                         if (rsurface.texture->shirttexture)
3011                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3012                         else
3013                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3014                 }
3015                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3016                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3017                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3018                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3019                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3020                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3021                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3022                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3023                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3024                         );
3025                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3026                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3027                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3028                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3029
3030                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3031                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3032                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3033                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3034                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3035                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3036                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3037                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3038                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3039                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3040                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3041                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3042                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3043                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3044                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3045                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3046                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3047                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3048                 {
3049                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3050                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3051                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3052                 }
3053                 else
3054                 {
3055                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3056                 }
3057 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3058                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3059                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3060                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3061                 {
3062                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3063                         if (rsurface.rtlight)
3064                         {
3065                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3066                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3067                         }
3068                 }
3069                 break;
3070         }
3071 }
3072
3073 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3074 {
3075         // select a permutation of the lighting shader appropriate to this
3076         // combination of texture, entity, light source, and fogging, only use the
3077         // minimum features necessary to avoid wasting rendering time in the
3078         // fragment shader on features that are not being used
3079         unsigned int permutation = 0;
3080         unsigned int mode = 0;
3081         const float *lightcolorbase = rtlight->currentcolor;
3082         float ambientscale = rtlight->ambientscale;
3083         float diffusescale = rtlight->diffusescale;
3084         float specularscale = rtlight->specularscale;
3085         // this is the location of the light in view space
3086         vec3_t viewlightorigin;
3087         // this transforms from view space (camera) to light space (cubemap)
3088         matrix4x4_t viewtolight;
3089         matrix4x4_t lighttoview;
3090         float viewtolight16f[16];
3091         // light source
3092         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3093         if (rtlight->currentcubemap != r_texture_whitecube)
3094                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3095         if (diffusescale > 0)
3096                 permutation |= SHADERPERMUTATION_DIFFUSE;
3097         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3098                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3099         if (r_shadow_usingshadowmap2d)
3100         {
3101                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3102                 if (r_shadow_shadowmapvsdct)
3103                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3104
3105                 if (r_shadow_shadowmap2ddepthbuffer)
3106                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3107         }
3108         if (vid.allowalphatocoverage)
3109                 GL_AlphaToCoverage(false);
3110         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3111         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3112         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3113         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3114         switch(vid.renderpath)
3115         {
3116         case RENDERPATH_D3D9:
3117 #ifdef SUPPORTD3D
3118                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3119                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3120                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3121                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3122                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3123                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3124                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3125                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3126                 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);
3127                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3128                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3129
3130                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3131                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3132                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3133                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3134                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3135 #endif
3136                 break;
3137         case RENDERPATH_D3D10:
3138                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3139                 break;
3140         case RENDERPATH_D3D11:
3141                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3142                 break;
3143         case RENDERPATH_GL20:
3144         case RENDERPATH_GLES2:
3145                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3146                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3147                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3148                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3149                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3150                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3151                 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]);
3152                 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]);
3153                 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);
3154                 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]);
3155                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3156
3157                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3158                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3159                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3160                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3161                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3162                 break;
3163         case RENDERPATH_GL11:
3164         case RENDERPATH_GL13:
3165         case RENDERPATH_GLES1:
3166                 break;
3167         case RENDERPATH_SOFT:
3168                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3169                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3170                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3171                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3172                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3173                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3174                 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]);
3175                 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]);
3176                 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);
3177                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3178                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3179
3180                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3181                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3182                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3183                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3184                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3185                 break;
3186         }
3187 }
3188
3189 #define SKINFRAME_HASH 1024
3190
3191 typedef struct
3192 {
3193         unsigned int loadsequence; // incremented each level change
3194         memexpandablearray_t array;
3195         skinframe_t *hash[SKINFRAME_HASH];
3196 }
3197 r_skinframe_t;
3198 r_skinframe_t r_skinframe;
3199
3200 void R_SkinFrame_PrepareForPurge(void)
3201 {
3202         r_skinframe.loadsequence++;
3203         // wrap it without hitting zero
3204         if (r_skinframe.loadsequence >= 200)
3205                 r_skinframe.loadsequence = 1;
3206 }
3207
3208 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3209 {
3210         if (!skinframe)
3211                 return;
3212         // mark the skinframe as used for the purging code
3213         skinframe->loadsequence = r_skinframe.loadsequence;
3214 }
3215
3216 void R_SkinFrame_Purge(void)
3217 {
3218         int i;
3219         skinframe_t *s;
3220         for (i = 0;i < SKINFRAME_HASH;i++)
3221         {
3222                 for (s = r_skinframe.hash[i];s;s = s->next)
3223                 {
3224                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3225                         {
3226                                 if (s->merged == s->base)
3227                                         s->merged = NULL;
3228                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3229                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3230                                 R_PurgeTexture(s->merged);s->merged = NULL;
3231                                 R_PurgeTexture(s->base  );s->base   = NULL;
3232                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3233                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3234                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3235                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3236                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3237                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3238                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3239                                 s->loadsequence = 0;
3240                         }
3241                 }
3242         }
3243 }
3244
3245 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3246         skinframe_t *item;
3247         char basename[MAX_QPATH];
3248
3249         Image_StripImageExtension(name, basename, sizeof(basename));
3250
3251         if( last == NULL ) {
3252                 int hashindex;
3253                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3254                 item = r_skinframe.hash[hashindex];
3255         } else {
3256                 item = last->next;
3257         }
3258
3259         // linearly search through the hash bucket
3260         for( ; item ; item = item->next ) {
3261                 if( !strcmp( item->basename, basename ) ) {
3262                         return item;
3263                 }
3264         }
3265         return NULL;
3266 }
3267
3268 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3269 {
3270         skinframe_t *item;
3271         int hashindex;
3272         char basename[MAX_QPATH];
3273
3274         Image_StripImageExtension(name, basename, sizeof(basename));
3275
3276         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3277         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3278                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3279                         break;
3280
3281         if (!item) {
3282                 rtexture_t *dyntexture;
3283                 // check whether its a dynamic texture
3284                 dyntexture = CL_GetDynTexture( basename );
3285                 if (!add && !dyntexture)
3286                         return NULL;
3287                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3288                 memset(item, 0, sizeof(*item));
3289                 strlcpy(item->basename, basename, sizeof(item->basename));
3290                 item->base = dyntexture; // either NULL or dyntexture handle
3291                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3292                 item->comparewidth = comparewidth;
3293                 item->compareheight = compareheight;
3294                 item->comparecrc = comparecrc;
3295                 item->next = r_skinframe.hash[hashindex];
3296                 r_skinframe.hash[hashindex] = item;
3297         }
3298         else if (textureflags & TEXF_FORCE_RELOAD)
3299         {
3300                 rtexture_t *dyntexture;
3301                 // check whether its a dynamic texture
3302                 dyntexture = CL_GetDynTexture( basename );
3303                 if (!add && !dyntexture)
3304                         return NULL;
3305                 if (item->merged == item->base)
3306                         item->merged = NULL;
3307                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3308                 R_PurgeTexture(item->stain );item->stain  = NULL;
3309                 R_PurgeTexture(item->merged);item->merged = NULL;
3310                 R_PurgeTexture(item->base  );item->base   = NULL;
3311                 R_PurgeTexture(item->pants );item->pants  = NULL;
3312                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3313                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3314                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3315                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3316                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3317         R_PurgeTexture(item->reflect);item->reflect = NULL;
3318                 item->loadsequence = 0;
3319         }
3320         else if( item->base == NULL )
3321         {
3322                 rtexture_t *dyntexture;
3323                 // check whether its a dynamic texture
3324                 // 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]
3325                 dyntexture = CL_GetDynTexture( basename );
3326                 item->base = dyntexture; // either NULL or dyntexture handle
3327         }
3328
3329         R_SkinFrame_MarkUsed(item);
3330         return item;
3331 }
3332
3333 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3334         { \
3335                 unsigned long long avgcolor[5], wsum; \
3336                 int pix, comp, w; \
3337                 avgcolor[0] = 0; \
3338                 avgcolor[1] = 0; \
3339                 avgcolor[2] = 0; \
3340                 avgcolor[3] = 0; \
3341                 avgcolor[4] = 0; \
3342                 wsum = 0; \
3343                 for(pix = 0; pix < cnt; ++pix) \
3344                 { \
3345                         w = 0; \
3346                         for(comp = 0; comp < 3; ++comp) \
3347                                 w += getpixel; \
3348                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3349                         { \
3350                                 ++wsum; \
3351                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3352                                 w = getpixel; \
3353                                 for(comp = 0; comp < 3; ++comp) \
3354                                         avgcolor[comp] += getpixel * w; \
3355                                 avgcolor[3] += w; \
3356                         } \
3357                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3358                         avgcolor[4] += getpixel; \
3359                 } \
3360                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3361                         avgcolor[3] = 1; \
3362                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3363                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3364                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3365                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3366         }
3367
3368 extern cvar_t gl_picmip;
3369 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3370 {
3371         int j;
3372         unsigned char *pixels;
3373         unsigned char *bumppixels;
3374         unsigned char *basepixels = NULL;
3375         int basepixels_width = 0;
3376         int basepixels_height = 0;
3377         skinframe_t *skinframe;
3378         rtexture_t *ddsbase = NULL;
3379         qboolean ddshasalpha = false;
3380         float ddsavgcolor[4];
3381         char basename[MAX_QPATH];
3382         int miplevel = R_PicmipForFlags(textureflags);
3383         int savemiplevel = miplevel;
3384         int mymiplevel;
3385         char vabuf[1024];
3386
3387         if (cls.state == ca_dedicated)
3388                 return NULL;
3389
3390         // return an existing skinframe if already loaded
3391         // if loading of the first image fails, don't make a new skinframe as it
3392         // would cause all future lookups of this to be missing
3393         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3394         if (skinframe && skinframe->base)
3395                 return skinframe;
3396
3397         Image_StripImageExtension(name, basename, sizeof(basename));
3398
3399         // check for DDS texture file first
3400         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3401         {
3402                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3403                 if (basepixels == NULL)
3404                         return NULL;
3405         }
3406
3407         // FIXME handle miplevel
3408
3409         if (developer_loading.integer)
3410                 Con_Printf("loading skin \"%s\"\n", name);
3411
3412         // we've got some pixels to store, so really allocate this new texture now
3413         if (!skinframe)
3414                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3415         textureflags &= ~TEXF_FORCE_RELOAD;
3416         skinframe->stain = NULL;
3417         skinframe->merged = NULL;
3418         skinframe->base = NULL;
3419         skinframe->pants = NULL;
3420         skinframe->shirt = NULL;
3421         skinframe->nmap = NULL;
3422         skinframe->gloss = NULL;
3423         skinframe->glow = NULL;
3424         skinframe->fog = NULL;
3425         skinframe->reflect = NULL;
3426         skinframe->hasalpha = false;
3427         // we could store the q2animname here too
3428
3429         if (ddsbase)
3430         {
3431                 skinframe->base = ddsbase;
3432                 skinframe->hasalpha = ddshasalpha;
3433                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3434                 if (r_loadfog && skinframe->hasalpha)
3435                         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);
3436                 //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]);
3437         }
3438         else
3439         {
3440                 basepixels_width = image_width;
3441                 basepixels_height = image_height;
3442                 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);
3443                 if (textureflags & TEXF_ALPHA)
3444                 {
3445                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3446                         {
3447                                 if (basepixels[j] < 255)
3448                                 {
3449                                         skinframe->hasalpha = true;
3450                                         break;
3451                                 }
3452                         }
3453                         if (r_loadfog && skinframe->hasalpha)
3454                         {
3455                                 // has transparent pixels
3456                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3457                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3458                                 {
3459                                         pixels[j+0] = 255;
3460                                         pixels[j+1] = 255;
3461                                         pixels[j+2] = 255;
3462                                         pixels[j+3] = basepixels[j+3];
3463                                 }
3464                                 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);
3465                                 Mem_Free(pixels);
3466                         }
3467                 }
3468                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3469 #ifndef USE_GLES2
3470                 //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]);
3471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3472                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3473                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3474                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3475 #endif
3476         }
3477
3478         if (r_loaddds)
3479         {
3480                 mymiplevel = savemiplevel;
3481                 if (r_loadnormalmap)
3482                         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);
3483                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3484                 if (r_loadgloss)
3485                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3486                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3487                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3488                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3489         }
3490
3491         // _norm is the name used by tenebrae and has been adopted as standard
3492         if (r_loadnormalmap && skinframe->nmap == NULL)
3493         {
3494                 mymiplevel = savemiplevel;
3495                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3496                 {
3497                         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);
3498                         Mem_Free(pixels);
3499                         pixels = NULL;
3500                 }
3501                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3502                 {
3503                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3504                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3505                         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);
3506                         Mem_Free(pixels);
3507                         Mem_Free(bumppixels);
3508                 }
3509                 else if (r_shadow_bumpscale_basetexture.value > 0)
3510                 {
3511                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3512                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3513                         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);
3514                         Mem_Free(pixels);
3515                 }
3516 #ifndef USE_GLES2
3517                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3518                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3519 #endif
3520         }
3521
3522         // _luma is supported only for tenebrae compatibility
3523         // _glow is the preferred name
3524         mymiplevel = savemiplevel;
3525         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))))
3526         {
3527                 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);
3528 #ifndef USE_GLES2
3529                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3530                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3531 #endif
3532                 Mem_Free(pixels);pixels = NULL;
3533         }
3534
3535         mymiplevel = savemiplevel;
3536         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3537         {
3538                 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);
3539 #ifndef USE_GLES2
3540                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3541                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3542 #endif
3543                 Mem_Free(pixels);
3544                 pixels = NULL;
3545         }
3546
3547         mymiplevel = savemiplevel;
3548         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3549         {
3550                 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);
3551 #ifndef USE_GLES2
3552                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3553                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3554 #endif
3555                 Mem_Free(pixels);
3556                 pixels = NULL;
3557         }
3558
3559         mymiplevel = savemiplevel;
3560         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3561         {
3562                 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);
3563 #ifndef USE_GLES2
3564                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3565                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3566 #endif
3567                 Mem_Free(pixels);
3568                 pixels = NULL;
3569         }
3570
3571         mymiplevel = savemiplevel;
3572         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3573         {
3574                 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);
3575 #ifndef USE_GLES2
3576                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3577                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3578 #endif
3579                 Mem_Free(pixels);
3580                 pixels = NULL;
3581         }
3582
3583         if (basepixels)
3584                 Mem_Free(basepixels);
3585
3586         return skinframe;
3587 }
3588
3589 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3590 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3591 {
3592         int i;
3593         skinframe_t *skinframe;
3594         char vabuf[1024];
3595
3596         if (cls.state == ca_dedicated)
3597                 return NULL;
3598
3599         // if already loaded just return it, otherwise make a new skinframe
3600         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3601         if (skinframe->base)
3602                 return skinframe;
3603         textureflags &= ~TEXF_FORCE_RELOAD;
3604
3605         skinframe->stain = NULL;
3606         skinframe->merged = NULL;
3607         skinframe->base = NULL;
3608         skinframe->pants = NULL;
3609         skinframe->shirt = NULL;
3610         skinframe->nmap = NULL;
3611         skinframe->gloss = NULL;
3612         skinframe->glow = NULL;
3613         skinframe->fog = NULL;
3614         skinframe->reflect = NULL;
3615         skinframe->hasalpha = false;
3616
3617         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3618         if (!skindata)
3619                 return NULL;
3620
3621         if (developer_loading.integer)
3622                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3623
3624         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3625         {
3626                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3627                 unsigned char *b = a + width * height * 4;
3628                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3629                 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);
3630                 Mem_Free(a);
3631         }
3632         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3633         if (textureflags & TEXF_ALPHA)
3634         {
3635                 for (i = 3;i < width * height * 4;i += 4)
3636                 {
3637                         if (skindata[i] < 255)
3638                         {
3639                                 skinframe->hasalpha = true;
3640                                 break;
3641                         }
3642                 }
3643                 if (r_loadfog && skinframe->hasalpha)
3644                 {
3645                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3646                         memcpy(fogpixels, skindata, width * height * 4);
3647                         for (i = 0;i < width * height * 4;i += 4)
3648                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3649                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3650                         Mem_Free(fogpixels);
3651                 }
3652         }
3653
3654         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3655         //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]);
3656
3657         return skinframe;
3658 }
3659
3660 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3661 {
3662         int i;
3663         int featuresmask;
3664         skinframe_t *skinframe;
3665
3666         if (cls.state == ca_dedicated)
3667                 return NULL;
3668
3669         // if already loaded just return it, otherwise make a new skinframe
3670         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3671         if (skinframe->base)
3672                 return skinframe;
3673         //textureflags &= ~TEXF_FORCE_RELOAD;
3674
3675         skinframe->stain = NULL;
3676         skinframe->merged = NULL;
3677         skinframe->base = NULL;
3678         skinframe->pants = NULL;
3679         skinframe->shirt = NULL;
3680         skinframe->nmap = NULL;
3681         skinframe->gloss = NULL;
3682         skinframe->glow = NULL;
3683         skinframe->fog = NULL;
3684         skinframe->reflect = NULL;
3685         skinframe->hasalpha = false;
3686
3687         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3688         if (!skindata)
3689                 return NULL;
3690
3691         if (developer_loading.integer)
3692                 Con_Printf("loading quake skin \"%s\"\n", name);
3693
3694         // 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)
3695         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3696         memcpy(skinframe->qpixels, skindata, width*height);
3697         skinframe->qwidth = width;
3698         skinframe->qheight = height;
3699
3700         featuresmask = 0;
3701         for (i = 0;i < width * height;i++)
3702                 featuresmask |= palette_featureflags[skindata[i]];
3703
3704         skinframe->hasalpha = false;
3705         // fence textures
3706         if (name[0] == '{')
3707                 skinframe->hasalpha = true;
3708         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3709         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3710         skinframe->qgeneratemerged = true;
3711         skinframe->qgeneratebase = skinframe->qhascolormapping;
3712         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3713
3714         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3715         //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]);
3716
3717         return skinframe;
3718 }
3719
3720 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3721 {
3722         int width;
3723         int height;
3724         unsigned char *skindata;
3725         char vabuf[1024];
3726
3727         if (!skinframe->qpixels)
3728                 return;
3729
3730         if (!skinframe->qhascolormapping)
3731                 colormapped = false;
3732
3733         if (colormapped)
3734         {
3735                 if (!skinframe->qgeneratebase)
3736                         return;
3737         }
3738         else
3739         {
3740                 if (!skinframe->qgeneratemerged)
3741                         return;
3742         }
3743
3744         width = skinframe->qwidth;
3745         height = skinframe->qheight;
3746         skindata = skinframe->qpixels;
3747
3748         if (skinframe->qgeneratenmap)
3749         {
3750                 unsigned char *a, *b;
3751                 skinframe->qgeneratenmap = false;
3752                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3753                 b = a + width * height * 4;
3754                 // use either a custom palette or the quake palette
3755                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3756                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3757                 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);
3758                 Mem_Free(a);
3759         }
3760
3761         if (skinframe->qgenerateglow)
3762         {
3763                 skinframe->qgenerateglow = false;
3764                 if (skinframe->hasalpha) // fence textures
3765                         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
3766                 else
3767                         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
3768         }
3769
3770         if (colormapped)
3771         {
3772                 skinframe->qgeneratebase = false;
3773                 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);
3774                 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);
3775                 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);
3776         }
3777         else
3778         {
3779                 skinframe->qgeneratemerged = false;
3780                 if (skinframe->hasalpha) // fence textures
3781                         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);
3782                 else
3783                         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);
3784         }
3785
3786         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3787         {
3788                 Mem_Free(skinframe->qpixels);
3789                 skinframe->qpixels = NULL;
3790         }
3791 }
3792
3793 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)
3794 {
3795         int i;
3796         skinframe_t *skinframe;
3797         char vabuf[1024];
3798
3799         if (cls.state == ca_dedicated)
3800                 return NULL;
3801
3802         // if already loaded just return it, otherwise make a new skinframe
3803         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3804         if (skinframe->base)
3805                 return skinframe;
3806         textureflags &= ~TEXF_FORCE_RELOAD;
3807
3808         skinframe->stain = NULL;
3809         skinframe->merged = NULL;
3810         skinframe->base = NULL;
3811         skinframe->pants = NULL;
3812         skinframe->shirt = NULL;
3813         skinframe->nmap = NULL;
3814         skinframe->gloss = NULL;
3815         skinframe->glow = NULL;
3816         skinframe->fog = NULL;
3817         skinframe->reflect = NULL;
3818         skinframe->hasalpha = false;
3819
3820         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3821         if (!skindata)
3822                 return NULL;
3823
3824         if (developer_loading.integer)
3825                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3826
3827         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3828         if (textureflags & TEXF_ALPHA)
3829         {
3830                 for (i = 0;i < width * height;i++)
3831                 {
3832                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3833                         {
3834                                 skinframe->hasalpha = true;
3835                                 break;
3836                         }
3837                 }
3838                 if (r_loadfog && skinframe->hasalpha)
3839                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3840         }
3841
3842         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3843         //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]);
3844
3845         return skinframe;
3846 }
3847
3848 skinframe_t *R_SkinFrame_LoadMissing(void)
3849 {
3850         skinframe_t *skinframe;
3851
3852         if (cls.state == ca_dedicated)
3853                 return NULL;
3854
3855         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3856         skinframe->stain = NULL;
3857         skinframe->merged = NULL;
3858         skinframe->base = NULL;
3859         skinframe->pants = NULL;
3860         skinframe->shirt = NULL;
3861         skinframe->nmap = NULL;
3862         skinframe->gloss = NULL;
3863         skinframe->glow = NULL;
3864         skinframe->fog = NULL;
3865         skinframe->reflect = NULL;
3866         skinframe->hasalpha = false;
3867
3868         skinframe->avgcolor[0] = rand() / RAND_MAX;
3869         skinframe->avgcolor[1] = rand() / RAND_MAX;
3870         skinframe->avgcolor[2] = rand() / RAND_MAX;
3871         skinframe->avgcolor[3] = 1;
3872
3873         return skinframe;
3874 }
3875
3876 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3877 typedef struct suffixinfo_s
3878 {
3879         const char *suffix;
3880         qboolean flipx, flipy, flipdiagonal;
3881 }
3882 suffixinfo_t;
3883 static suffixinfo_t suffix[3][6] =
3884 {
3885         {
3886                 {"px",   false, false, false},
3887                 {"nx",   false, false, false},
3888                 {"py",   false, false, false},
3889                 {"ny",   false, false, false},
3890                 {"pz",   false, false, false},
3891                 {"nz",   false, false, false}
3892         },
3893         {
3894                 {"posx", false, false, false},
3895                 {"negx", false, false, false},
3896                 {"posy", false, false, false},
3897                 {"negy", false, false, false},
3898                 {"posz", false, false, false},
3899                 {"negz", false, false, false}
3900         },
3901         {
3902                 {"rt",    true, false,  true},
3903                 {"lf",   false,  true,  true},
3904                 {"ft",    true,  true, false},
3905                 {"bk",   false, false, false},
3906                 {"up",    true, false,  true},
3907                 {"dn",    true, false,  true}
3908         }
3909 };
3910
3911 static int componentorder[4] = {0, 1, 2, 3};
3912
3913 static rtexture_t *R_LoadCubemap(const char *basename)
3914 {
3915         int i, j, cubemapsize;
3916         unsigned char *cubemappixels, *image_buffer;
3917         rtexture_t *cubemaptexture;
3918         char name[256];
3919         // must start 0 so the first loadimagepixels has no requested width/height
3920         cubemapsize = 0;
3921         cubemappixels = NULL;
3922         cubemaptexture = NULL;
3923         // keep trying different suffix groups (posx, px, rt) until one loads
3924         for (j = 0;j < 3 && !cubemappixels;j++)
3925         {
3926                 // load the 6 images in the suffix group
3927                 for (i = 0;i < 6;i++)
3928                 {
3929                         // generate an image name based on the base and and suffix
3930                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3931                         // load it
3932                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3933                         {
3934                                 // an image loaded, make sure width and height are equal
3935                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3936                                 {
3937                                         // if this is the first image to load successfully, allocate the cubemap memory
3938                                         if (!cubemappixels && image_width >= 1)
3939                                         {
3940                                                 cubemapsize = image_width;
3941                                                 // note this clears to black, so unavailable sides are black
3942                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3943                                         }
3944                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3945                                         if (cubemappixels)
3946                                                 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);
3947                                 }
3948                                 else
3949                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3950                                 // free the image
3951                                 Mem_Free(image_buffer);
3952                         }
3953                 }
3954         }
3955         // if a cubemap loaded, upload it
3956         if (cubemappixels)
3957         {
3958                 if (developer_loading.integer)
3959                         Con_Printf("loading cubemap \"%s\"\n", basename);
3960
3961                 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);
3962                 Mem_Free(cubemappixels);
3963         }
3964         else
3965         {
3966                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3967                 if (developer_loading.integer)
3968                 {
3969                         Con_Printf("(tried tried images ");
3970                         for (j = 0;j < 3;j++)
3971                                 for (i = 0;i < 6;i++)
3972                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3973                         Con_Print(" and was unable to find any of them).\n");
3974                 }
3975         }
3976         return cubemaptexture;
3977 }
3978
3979 rtexture_t *R_GetCubemap(const char *basename)
3980 {
3981         int i;
3982         for (i = 0;i < r_texture_numcubemaps;i++)
3983                 if (r_texture_cubemaps[i] != NULL)
3984                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3985                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3986         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3987                 return r_texture_whitecube;
3988         r_texture_numcubemaps++;
3989         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3990         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3991         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3992         return r_texture_cubemaps[i]->texture;
3993 }
3994
3995 static void R_Main_FreeViewCache(void)
3996 {
3997         if (r_refdef.viewcache.entityvisible)
3998                 Mem_Free(r_refdef.viewcache.entityvisible);
3999         if (r_refdef.viewcache.world_pvsbits)
4000                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4001         if (r_refdef.viewcache.world_leafvisible)
4002                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4003         if (r_refdef.viewcache.world_surfacevisible)
4004                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4006 }
4007
4008 static void R_Main_ResizeViewCache(void)
4009 {
4010         int numentities = r_refdef.scene.numentities;
4011         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4012         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4013         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4014         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4015         if (r_refdef.viewcache.maxentities < numentities)
4016         {
4017                 r_refdef.viewcache.maxentities = numentities;
4018                 if (r_refdef.viewcache.entityvisible)
4019                         Mem_Free(r_refdef.viewcache.entityvisible);
4020                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4021         }
4022         if (r_refdef.viewcache.world_numclusters != numclusters)
4023         {
4024                 r_refdef.viewcache.world_numclusters = numclusters;
4025                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4026                 if (r_refdef.viewcache.world_pvsbits)
4027                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4028                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4029         }
4030         if (r_refdef.viewcache.world_numleafs != numleafs)
4031         {
4032                 r_refdef.viewcache.world_numleafs = numleafs;
4033                 if (r_refdef.viewcache.world_leafvisible)
4034                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4035                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4036         }
4037         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4038         {
4039                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4040                 if (r_refdef.viewcache.world_surfacevisible)
4041                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4042                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4043         }
4044 }
4045
4046 extern rtexture_t *loadingscreentexture;
4047 static void gl_main_start(void)
4048 {
4049         loadingscreentexture = NULL;
4050         r_texture_blanknormalmap = NULL;
4051         r_texture_white = NULL;
4052         r_texture_grey128 = NULL;
4053         r_texture_black = NULL;
4054         r_texture_whitecube = NULL;
4055         r_texture_normalizationcube = NULL;
4056         r_texture_fogattenuation = NULL;
4057         r_texture_fogheighttexture = NULL;
4058         r_texture_gammaramps = NULL;
4059         r_texture_numcubemaps = 0;
4060         r_uniformbufferalignment = 32;
4061
4062         r_loaddds = r_texture_dds_load.integer != 0;
4063         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4064
4065         switch(vid.renderpath)
4066         {
4067         case RENDERPATH_GL20:
4068         case RENDERPATH_D3D9:
4069         case RENDERPATH_D3D10:
4070         case RENDERPATH_D3D11:
4071         case RENDERPATH_SOFT:
4072         case RENDERPATH_GLES2:
4073                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4074                 Cvar_SetValueQuick(&gl_combine, 1);
4075                 Cvar_SetValueQuick(&r_glsl, 1);
4076                 r_loadnormalmap = true;
4077                 r_loadgloss = true;
4078                 r_loadfog = false;
4079 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4080                 if (vid.support.arb_uniform_buffer_object)
4081                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4082 #endif
4083                         break;
4084         case RENDERPATH_GL13:
4085         case RENDERPATH_GLES1:
4086                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4087                 Cvar_SetValueQuick(&gl_combine, 1);
4088                 Cvar_SetValueQuick(&r_glsl, 0);
4089                 r_loadnormalmap = false;
4090                 r_loadgloss = false;
4091                 r_loadfog = true;
4092                 break;
4093         case RENDERPATH_GL11:
4094                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4095                 Cvar_SetValueQuick(&gl_combine, 0);
4096                 Cvar_SetValueQuick(&r_glsl, 0);
4097                 r_loadnormalmap = false;
4098                 r_loadgloss = false;
4099                 r_loadfog = true;
4100                 break;
4101         }
4102
4103         R_AnimCache_Free();
4104         R_FrameData_Reset();
4105         R_BufferData_Reset();
4106
4107         r_numqueries = 0;
4108         r_maxqueries = 0;
4109         memset(r_queries, 0, sizeof(r_queries));
4110
4111         r_qwskincache = NULL;
4112         r_qwskincache_size = 0;
4113
4114         // due to caching of texture_t references, the collision cache must be reset
4115         Collision_Cache_Reset(true);
4116
4117         // set up r_skinframe loading system for textures
4118         memset(&r_skinframe, 0, sizeof(r_skinframe));
4119         r_skinframe.loadsequence = 1;
4120         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4121
4122         r_main_texturepool = R_AllocTexturePool();
4123         R_BuildBlankTextures();
4124         R_BuildNoTexture();
4125         if (vid.support.arb_texture_cube_map)
4126         {
4127                 R_BuildWhiteCube();
4128                 R_BuildNormalizationCube();
4129         }
4130         r_texture_fogattenuation = NULL;
4131         r_texture_fogheighttexture = NULL;
4132         r_texture_gammaramps = NULL;
4133         //r_texture_fogintensity = NULL;
4134         memset(&r_fb, 0, sizeof(r_fb));
4135         r_glsl_permutation = NULL;
4136         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4137         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4138 #ifdef SUPPORTD3D
4139         r_hlsl_permutation = NULL;
4140         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4141         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4142 #endif
4143         memset(&r_svbsp, 0, sizeof (r_svbsp));
4144
4145         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4146         r_texture_numcubemaps = 0;
4147
4148         r_refdef.fogmasktable_density = 0;
4149
4150 #ifdef __ANDROID__
4151         // For Steelstorm Android
4152         // FIXME CACHE the program and reload
4153         // FIXME see possible combinations for SS:BR android
4154         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4155         R_SetupShader_SetPermutationGLSL(0, 12);
4156         R_SetupShader_SetPermutationGLSL(0, 13);
4157         R_SetupShader_SetPermutationGLSL(0, 8388621);
4158         R_SetupShader_SetPermutationGLSL(3, 0);
4159         R_SetupShader_SetPermutationGLSL(3, 2048);
4160         R_SetupShader_SetPermutationGLSL(5, 0);
4161         R_SetupShader_SetPermutationGLSL(5, 2);
4162         R_SetupShader_SetPermutationGLSL(5, 2048);
4163         R_SetupShader_SetPermutationGLSL(5, 8388608);
4164         R_SetupShader_SetPermutationGLSL(11, 1);
4165         R_SetupShader_SetPermutationGLSL(11, 2049);
4166         R_SetupShader_SetPermutationGLSL(11, 8193);
4167         R_SetupShader_SetPermutationGLSL(11, 10241);
4168         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4169 #endif
4170 }
4171
4172 static void gl_main_shutdown(void)
4173 {
4174         R_AnimCache_Free();
4175         R_FrameData_Reset();
4176         R_BufferData_Reset();
4177
4178         R_Main_FreeViewCache();
4179
4180         switch(vid.renderpath)
4181         {
4182         case RENDERPATH_GL11:
4183         case RENDERPATH_GL13:
4184         case RENDERPATH_GL20:
4185         case RENDERPATH_GLES1:
4186         case RENDERPATH_GLES2:
4187 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4188                 if (r_maxqueries)
4189                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4190 #endif
4191                 break;
4192         case RENDERPATH_D3D9:
4193                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4194                 break;
4195         case RENDERPATH_D3D10:
4196                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4197                 break;
4198         case RENDERPATH_D3D11:
4199                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4200                 break;
4201         case RENDERPATH_SOFT:
4202                 break;
4203         }
4204
4205         r_numqueries = 0;
4206         r_maxqueries = 0;
4207         memset(r_queries, 0, sizeof(r_queries));
4208
4209         r_qwskincache = NULL;
4210         r_qwskincache_size = 0;
4211
4212         // clear out the r_skinframe state
4213         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4214         memset(&r_skinframe, 0, sizeof(r_skinframe));
4215
4216         if (r_svbsp.nodes)
4217                 Mem_Free(r_svbsp.nodes);
4218         memset(&r_svbsp, 0, sizeof (r_svbsp));
4219         R_FreeTexturePool(&r_main_texturepool);
4220         loadingscreentexture = NULL;
4221         r_texture_blanknormalmap = NULL;
4222         r_texture_white = NULL;
4223         r_texture_grey128 = NULL;
4224         r_texture_black = NULL;
4225         r_texture_whitecube = NULL;
4226         r_texture_normalizationcube = NULL;
4227         r_texture_fogattenuation = NULL;
4228         r_texture_fogheighttexture = NULL;
4229         r_texture_gammaramps = NULL;
4230         r_texture_numcubemaps = 0;
4231         //r_texture_fogintensity = NULL;
4232         memset(&r_fb, 0, sizeof(r_fb));
4233         R_GLSL_Restart_f();
4234
4235         r_glsl_permutation = NULL;
4236         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4237         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4238 #ifdef SUPPORTD3D
4239         r_hlsl_permutation = NULL;
4240         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4241         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4242 #endif
4243 }
4244
4245 static void gl_main_newmap(void)
4246 {
4247         // FIXME: move this code to client
4248         char *entities, entname[MAX_QPATH];
4249         if (r_qwskincache)
4250                 Mem_Free(r_qwskincache);
4251         r_qwskincache = NULL;
4252         r_qwskincache_size = 0;
4253         if (cl.worldmodel)
4254         {
4255                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4256                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4257                 {
4258                         CL_ParseEntityLump(entities);
4259                         Mem_Free(entities);
4260                         return;
4261                 }
4262                 if (cl.worldmodel->brush.entities)
4263                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4264         }
4265         R_Main_FreeViewCache();
4266
4267         R_FrameData_Reset();
4268         R_BufferData_Reset();
4269 }
4270
4271 void GL_Main_Init(void)
4272 {
4273         int i;
4274         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4275         R_InitShaderModeInfo();
4276
4277         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4278         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4279         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4280         if (gamemode == GAME_NEHAHRA)
4281         {
4282                 Cvar_RegisterVariable (&gl_fogenable);
4283                 Cvar_RegisterVariable (&gl_fogdensity);
4284                 Cvar_RegisterVariable (&gl_fogred);
4285                 Cvar_RegisterVariable (&gl_foggreen);
4286                 Cvar_RegisterVariable (&gl_fogblue);
4287                 Cvar_RegisterVariable (&gl_fogstart);
4288                 Cvar_RegisterVariable (&gl_fogend);
4289                 Cvar_RegisterVariable (&gl_skyclip);
4290         }
4291         Cvar_RegisterVariable(&r_motionblur);
4292         Cvar_RegisterVariable(&r_damageblur);
4293         Cvar_RegisterVariable(&r_motionblur_averaging);
4294         Cvar_RegisterVariable(&r_motionblur_randomize);
4295         Cvar_RegisterVariable(&r_motionblur_minblur);
4296         Cvar_RegisterVariable(&r_motionblur_maxblur);
4297         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4298         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4299         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4300         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4301         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4302         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4303         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4304         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4305         Cvar_RegisterVariable(&r_equalize_entities_by);
4306         Cvar_RegisterVariable(&r_equalize_entities_to);
4307         Cvar_RegisterVariable(&r_depthfirst);
4308         Cvar_RegisterVariable(&r_useinfinitefarclip);
4309         Cvar_RegisterVariable(&r_farclip_base);
4310         Cvar_RegisterVariable(&r_farclip_world);
4311         Cvar_RegisterVariable(&r_nearclip);
4312         Cvar_RegisterVariable(&r_deformvertexes);
4313         Cvar_RegisterVariable(&r_transparent);
4314         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4315         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4316         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4317         Cvar_RegisterVariable(&r_showoverdraw);
4318         Cvar_RegisterVariable(&r_showbboxes);
4319         Cvar_RegisterVariable(&r_showsurfaces);
4320         Cvar_RegisterVariable(&r_showtris);
4321         Cvar_RegisterVariable(&r_shownormals);
4322         Cvar_RegisterVariable(&r_showlighting);
4323         Cvar_RegisterVariable(&r_showshadowvolumes);
4324         Cvar_RegisterVariable(&r_showcollisionbrushes);
4325         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4326         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4327         Cvar_RegisterVariable(&r_showdisabledepthtest);
4328         Cvar_RegisterVariable(&r_drawportals);
4329         Cvar_RegisterVariable(&r_drawentities);
4330         Cvar_RegisterVariable(&r_draw2d);
4331         Cvar_RegisterVariable(&r_drawworld);
4332         Cvar_RegisterVariable(&r_cullentities_trace);
4333         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4334         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4335         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4336         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4337         Cvar_RegisterVariable(&r_sortentities);
4338         Cvar_RegisterVariable(&r_drawviewmodel);
4339         Cvar_RegisterVariable(&r_drawexteriormodel);
4340         Cvar_RegisterVariable(&r_speeds);
4341         Cvar_RegisterVariable(&r_fullbrights);
4342         Cvar_RegisterVariable(&r_wateralpha);
4343         Cvar_RegisterVariable(&r_dynamic);
4344         Cvar_RegisterVariable(&r_fakelight);
4345         Cvar_RegisterVariable(&r_fakelight_intensity);
4346         Cvar_RegisterVariable(&r_fullbright);
4347         Cvar_RegisterVariable(&r_shadows);
4348         Cvar_RegisterVariable(&r_shadows_darken);
4349         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4350         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4351         Cvar_RegisterVariable(&r_shadows_throwdistance);
4352         Cvar_RegisterVariable(&r_shadows_throwdirection);
4353         Cvar_RegisterVariable(&r_shadows_focus);
4354         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4355         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4356         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4357         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4358         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4359         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4360         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4361         Cvar_RegisterVariable(&r_fog_exp2);
4362         Cvar_RegisterVariable(&r_fog_clear);
4363         Cvar_RegisterVariable(&r_drawfog);
4364         Cvar_RegisterVariable(&r_transparentdepthmasking);
4365         Cvar_RegisterVariable(&r_transparent_sortmindist);
4366         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4367         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4368         Cvar_RegisterVariable(&r_texture_dds_load);
4369         Cvar_RegisterVariable(&r_texture_dds_save);
4370         Cvar_RegisterVariable(&r_textureunits);
4371         Cvar_RegisterVariable(&gl_combine);
4372         Cvar_RegisterVariable(&r_usedepthtextures);
4373         Cvar_RegisterVariable(&r_viewfbo);
4374         Cvar_RegisterVariable(&r_viewscale);
4375         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4376         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4377         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4378         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4379         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4380         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4381         Cvar_RegisterVariable(&r_glsl);
4382         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4383         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4384         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4385         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4386         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4387         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4388         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4389         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4390         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4391         Cvar_RegisterVariable(&r_glsl_postprocess);
4392         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4393         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4394         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4395         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4396         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4397         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4398         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4399         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4400         Cvar_RegisterVariable(&r_celshading);
4401         Cvar_RegisterVariable(&r_celoutlines);
4402
4403         Cvar_RegisterVariable(&r_water);
4404         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4405         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4406         Cvar_RegisterVariable(&r_water_clippingplanebias);
4407         Cvar_RegisterVariable(&r_water_refractdistort);
4408         Cvar_RegisterVariable(&r_water_reflectdistort);
4409         Cvar_RegisterVariable(&r_water_scissormode);
4410         Cvar_RegisterVariable(&r_water_lowquality);
4411         Cvar_RegisterVariable(&r_water_hideplayer);
4412         Cvar_RegisterVariable(&r_water_fbo);
4413
4414         Cvar_RegisterVariable(&r_lerpsprites);
4415         Cvar_RegisterVariable(&r_lerpmodels);
4416         Cvar_RegisterVariable(&r_lerplightstyles);
4417         Cvar_RegisterVariable(&r_waterscroll);
4418         Cvar_RegisterVariable(&r_bloom);
4419         Cvar_RegisterVariable(&r_bloom_colorscale);
4420         Cvar_RegisterVariable(&r_bloom_brighten);
4421         Cvar_RegisterVariable(&r_bloom_blur);
4422         Cvar_RegisterVariable(&r_bloom_resolution);
4423         Cvar_RegisterVariable(&r_bloom_colorexponent);
4424         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4425         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4426         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4427         Cvar_RegisterVariable(&r_hdr_glowintensity);
4428         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4429         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4430         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4431         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4432         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4433         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4434         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4435         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4436         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4437         Cvar_RegisterVariable(&developer_texturelogging);
4438         Cvar_RegisterVariable(&gl_lightmaps);
4439         Cvar_RegisterVariable(&r_test);
4440         Cvar_RegisterVariable(&r_batch_multidraw);
4441         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4442         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4443         Cvar_RegisterVariable(&r_glsl_skeletal);
4444         Cvar_RegisterVariable(&r_glsl_saturation);
4445         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4446         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4447         Cvar_RegisterVariable(&r_framedatasize);
4448         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4449                 Cvar_RegisterVariable(&r_buffermegs[i]);
4450         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4451         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4452                 Cvar_SetValue("r_fullbrights", 0);
4453 #ifdef DP_MOBILETOUCH
4454         // GLES devices have terrible depth precision in general, so...
4455         Cvar_SetValueQuick(&r_nearclip, 4);
4456         Cvar_SetValueQuick(&r_farclip_base, 4096);
4457         Cvar_SetValueQuick(&r_farclip_world, 0);
4458         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4459 #endif
4460         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4461 }
4462
4463 void Render_Init(void)
4464 {
4465         gl_backend_init();
4466         R_Textures_Init();
4467         GL_Main_Init();
4468         Font_Init();
4469         GL_Draw_Init();
4470         R_Shadow_Init();
4471         R_Sky_Init();
4472         GL_Surf_Init();
4473         Sbar_Init();
4474         R_Particles_Init();
4475         R_Explosion_Init();
4476         R_LightningBeams_Init();
4477         Mod_RenderInit();
4478 }
4479
4480 /*
4481 ===============
4482 GL_Init
4483 ===============
4484 */
4485 #ifndef USE_GLES2
4486 extern char *ENGINE_EXTENSIONS;
4487 void GL_Init (void)
4488 {
4489         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4490         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4491         gl_version = (const char *)qglGetString(GL_VERSION);
4492         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4493
4494         if (!gl_extensions)
4495                 gl_extensions = "";
4496         if (!gl_platformextensions)
4497                 gl_platformextensions = "";
4498
4499         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4500         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4501         Con_Printf("GL_VERSION: %s\n", gl_version);
4502         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4503         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4504
4505         VID_CheckExtensions();
4506
4507         // LordHavoc: report supported extensions
4508 #ifdef CONFIG_MENU
4509         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4510 #else
4511         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4512 #endif
4513
4514         // clear to black (loading plaque will be seen over this)
4515         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4516 }
4517 #endif
4518
4519 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4520 {
4521         int i;
4522         mplane_t *p;
4523         if (r_trippy.integer)
4524                 return false;
4525         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4526         {
4527                 p = r_refdef.view.frustum + i;
4528                 switch(p->signbits)
4529                 {
4530                 default:
4531                 case 0:
4532                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4533                                 return true;
4534                         break;
4535                 case 1:
4536                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4537                                 return true;
4538                         break;
4539                 case 2:
4540                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4541                                 return true;
4542                         break;
4543                 case 3:
4544                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4545                                 return true;
4546                         break;
4547                 case 4:
4548                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4549                                 return true;
4550                         break;
4551                 case 5:
4552                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4553                                 return true;
4554                         break;
4555                 case 6:
4556                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4557                                 return true;
4558                         break;
4559                 case 7:
4560                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4561                                 return true;
4562                         break;
4563                 }
4564         }
4565         return false;
4566 }
4567
4568 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4569 {
4570         int i;
4571         const mplane_t *p;
4572         if (r_trippy.integer)
4573                 return false;
4574         for (i = 0;i < numplanes;i++)
4575         {
4576                 p = planes + i;
4577                 switch(p->signbits)
4578                 {
4579                 default:
4580                 case 0:
4581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4582                                 return true;
4583                         break;
4584                 case 1:
4585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4586                                 return true;
4587                         break;
4588                 case 2:
4589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4590                                 return true;
4591                         break;
4592                 case 3:
4593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4594                                 return true;
4595                         break;
4596                 case 4:
4597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4598                                 return true;
4599                         break;
4600                 case 5:
4601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4602                                 return true;
4603                         break;
4604                 case 6:
4605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4606                                 return true;
4607                         break;
4608                 case 7:
4609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4610                                 return true;
4611                         break;
4612                 }
4613         }
4614         return false;
4615 }
4616
4617 //==================================================================================
4618
4619 // LordHavoc: this stores temporary data used within the same frame
4620
4621 typedef struct r_framedata_mem_s
4622 {
4623         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4624         size_t size; // how much usable space
4625         size_t current; // how much space in use
4626         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4627         size_t wantedsize; // how much space was allocated
4628         unsigned char *data; // start of real data (16byte aligned)
4629 }
4630 r_framedata_mem_t;
4631
4632 static r_framedata_mem_t *r_framedata_mem;
4633
4634 void R_FrameData_Reset(void)
4635 {
4636         while (r_framedata_mem)
4637         {
4638                 r_framedata_mem_t *next = r_framedata_mem->purge;
4639                 Mem_Free(r_framedata_mem);
4640                 r_framedata_mem = next;
4641         }
4642 }
4643
4644 static void R_FrameData_Resize(qboolean mustgrow)
4645 {
4646         size_t wantedsize;
4647         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4648         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4649         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4650         {
4651                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4652                 newmem->wantedsize = wantedsize;
4653                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4654                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4655                 newmem->current = 0;
4656                 newmem->mark = 0;
4657                 newmem->purge = r_framedata_mem;
4658                 r_framedata_mem = newmem;
4659         }
4660 }
4661
4662 void R_FrameData_NewFrame(void)
4663 {
4664         R_FrameData_Resize(false);
4665         if (!r_framedata_mem)
4666                 return;
4667         // if we ran out of space on the last frame, free the old memory now
4668         while (r_framedata_mem->purge)
4669         {
4670                 // repeatedly remove the second item in the list, leaving only head
4671                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4672                 Mem_Free(r_framedata_mem->purge);
4673                 r_framedata_mem->purge = next;
4674         }
4675         // reset the current mem pointer
4676         r_framedata_mem->current = 0;
4677         r_framedata_mem->mark = 0;
4678 }
4679
4680 void *R_FrameData_Alloc(size_t size)
4681 {
4682         void *data;
4683         float newvalue;
4684
4685         // align to 16 byte boundary - the data pointer is already aligned, so we
4686         // only need to ensure the size of every allocation is also aligned
4687         size = (size + 15) & ~15;
4688
4689         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4690         {
4691                 // emergency - we ran out of space, allocate more memory
4692                 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4693                 newvalue = r_framedatasize.value * 2.0f;
4694                 // 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
4695                 if (sizeof(size_t) >= 8)
4696                         newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4697                 else
4698                         newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4699                 // this might not be a growing it, but we'll allocate another buffer every time
4700                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4701                 R_FrameData_Resize(true);
4702         }
4703
4704         data = r_framedata_mem->data + r_framedata_mem->current;
4705         r_framedata_mem->current += size;
4706
4707         // count the usage for stats
4708         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4709         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4710
4711         return (void *)data;
4712 }
4713
4714 void *R_FrameData_Store(size_t size, void *data)
4715 {
4716         void *d = R_FrameData_Alloc(size);
4717         if (d && data)
4718                 memcpy(d, data, size);
4719         return d;
4720 }
4721
4722 void R_FrameData_SetMark(void)
4723 {
4724         if (!r_framedata_mem)
4725                 return;
4726         r_framedata_mem->mark = r_framedata_mem->current;
4727 }
4728
4729 void R_FrameData_ReturnToMark(void)
4730 {
4731         if (!r_framedata_mem)
4732                 return;
4733         r_framedata_mem->current = r_framedata_mem->mark;
4734 }
4735
4736 //==================================================================================
4737
4738 // avoid reusing the same buffer objects on consecutive frames
4739 #define R_BUFFERDATA_CYCLE 3
4740
4741 typedef struct r_bufferdata_buffer_s
4742 {
4743         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4744         size_t size; // how much usable space
4745         size_t current; // how much space in use
4746         r_meshbuffer_t *buffer; // the buffer itself
4747 }
4748 r_bufferdata_buffer_t;
4749
4750 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4751 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4752
4753 /// frees all dynamic buffers
4754 void R_BufferData_Reset(void)
4755 {
4756         int cycle, type;
4757         r_bufferdata_buffer_t **p, *mem;
4758         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4759         {
4760                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4761                 {
4762                         // free all buffers
4763                         p = &r_bufferdata_buffer[cycle][type];
4764                         while (*p)
4765                         {
4766                                 mem = *p;
4767                                 *p = (*p)->purge;
4768                                 if (mem->buffer)
4769                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4770                                 Mem_Free(mem);
4771                         }
4772                 }
4773         }
4774 }
4775
4776 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4777 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4778 {
4779         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4780         size_t size;
4781         float newvalue = r_buffermegs[type].value;
4782
4783         // increase the cvar if we have to (but only if we already have a mem)
4784         if (mustgrow && mem)
4785                 newvalue *= 2.0f;
4786         newvalue = bound(0.25f, newvalue, 256.0f);
4787         while (newvalue * 1024*1024 < minsize)
4788                 newvalue *= 2.0f;
4789
4790         // clamp the cvar to valid range
4791         newvalue = bound(0.25f, newvalue, 256.0f);
4792         if (r_buffermegs[type].value != newvalue)
4793                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4794
4795         // calculate size in bytes
4796         size = (size_t)(newvalue * 1024*1024);
4797         size = bound(131072, size, 256*1024*1024);
4798
4799         // allocate a new buffer if the size is different (purge old one later)
4800         // or if we were told we must grow the buffer
4801         if (!mem || mem->size != size || mustgrow)
4802         {
4803                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4804                 mem->size = size;
4805                 mem->current = 0;
4806                 if (type == R_BUFFERDATA_VERTEX)
4807                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4808                 else if (type == R_BUFFERDATA_INDEX16)
4809                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4810                 else if (type == R_BUFFERDATA_INDEX32)
4811                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4812                 else if (type == R_BUFFERDATA_UNIFORM)
4813                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4814                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4815                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4816         }
4817 }
4818
4819 void R_BufferData_NewFrame(void)
4820 {
4821         int type;
4822         r_bufferdata_buffer_t **p, *mem;
4823         // cycle to the next frame's buffers
4824         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4825         // if we ran out of space on the last time we used these buffers, free the old memory now
4826         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4827         {
4828                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4829                 {
4830                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4831                         // free all but the head buffer, this is how we recycle obsolete
4832                         // buffers after they are no longer in use
4833                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4834                         while (*p)
4835                         {
4836                                 mem = *p;
4837                                 *p = (*p)->purge;
4838                                 if (mem->buffer)
4839                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4840                                 Mem_Free(mem);
4841                         }
4842                         // reset the current offset
4843                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4844                 }
4845         }
4846 }
4847
4848 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4849 {
4850         r_bufferdata_buffer_t *mem;
4851         int offset = 0;
4852         int padsize;
4853
4854         *returnbufferoffset = 0;
4855
4856         // align size to a byte boundary appropriate for the buffer type, this
4857         // makes all allocations have aligned start offsets
4858         if (type == R_BUFFERDATA_UNIFORM)
4859                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4860         else
4861                 padsize = (datasize + 15) & ~15;
4862
4863         // if we ran out of space in this buffer we must allocate a new one
4864         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)
4865                 R_BufferData_Resize(type, true, padsize);
4866
4867         // if the resize did not give us enough memory, fail
4868         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)
4869                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4870
4871         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4872         offset = (int)mem->current;
4873         mem->current += padsize;
4874
4875         // upload the data to the buffer at the chosen offset
4876         if (offset == 0)
4877                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4878         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4879
4880         // count the usage for stats
4881         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4882         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4883
4884         // return the buffer offset
4885         *returnbufferoffset = offset;
4886
4887         return mem->buffer;
4888 }
4889
4890 //==================================================================================
4891
4892 // LordHavoc: animcache originally written by Echon, rewritten since then
4893
4894 /**
4895  * Animation cache prevents re-generating mesh data for an animated model
4896  * multiple times in one frame for lighting, shadowing, reflections, etc.
4897  */
4898
4899 void R_AnimCache_Free(void)
4900 {
4901 }
4902
4903 void R_AnimCache_ClearCache(void)
4904 {
4905         int i;
4906         entity_render_t *ent;
4907
4908         for (i = 0;i < r_refdef.scene.numentities;i++)
4909         {
4910                 ent = r_refdef.scene.entities[i];
4911                 ent->animcache_vertex3f = NULL;
4912                 ent->animcache_vertex3f_vertexbuffer = NULL;
4913                 ent->animcache_vertex3f_bufferoffset = 0;
4914                 ent->animcache_normal3f = NULL;
4915                 ent->animcache_normal3f_vertexbuffer = NULL;
4916                 ent->animcache_normal3f_bufferoffset = 0;
4917                 ent->animcache_svector3f = NULL;
4918                 ent->animcache_svector3f_vertexbuffer = NULL;
4919                 ent->animcache_svector3f_bufferoffset = 0;
4920                 ent->animcache_tvector3f = NULL;
4921                 ent->animcache_tvector3f_vertexbuffer = NULL;
4922                 ent->animcache_tvector3f_bufferoffset = 0;
4923                 ent->animcache_vertexmesh = NULL;
4924                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4925                 ent->animcache_vertexmesh_bufferoffset = 0;
4926                 ent->animcache_skeletaltransform3x4 = NULL;
4927                 ent->animcache_skeletaltransform3x4buffer = NULL;
4928                 ent->animcache_skeletaltransform3x4offset = 0;
4929                 ent->animcache_skeletaltransform3x4size = 0;
4930         }
4931 }
4932
4933 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4934 {
4935         int i;
4936
4937         // check if we need the meshbuffers
4938         if (!vid.useinterleavedarrays)
4939                 return;
4940
4941         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4942                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4943         // TODO: upload vertexbuffer?
4944         if (ent->animcache_vertexmesh)
4945         {
4946                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4947                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4948                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4949                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4950                 for (i = 0;i < numvertices;i++)
4951                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4952                 if (ent->animcache_svector3f)
4953                         for (i = 0;i < numvertices;i++)
4954                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4955                 if (ent->animcache_tvector3f)
4956                         for (i = 0;i < numvertices;i++)
4957                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4958                 if (ent->animcache_normal3f)
4959                         for (i = 0;i < numvertices;i++)
4960                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4961         }
4962 }
4963
4964 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4965 {
4966         dp_model_t *model = ent->model;
4967         int numvertices;
4968
4969         // see if this ent is worth caching
4970         if (!model || !model->Draw || !model->AnimateVertices)
4971                 return false;
4972         // nothing to cache if it contains no animations and has no skeleton
4973         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4974                 return false;
4975         // see if it is already cached for gpuskeletal
4976         if (ent->animcache_skeletaltransform3x4)
4977                 return false;
4978         // see if it is already cached as a mesh
4979         if (ent->animcache_vertex3f)
4980         {
4981                 // check if we need to add normals or tangents
4982                 if (ent->animcache_normal3f)
4983                         wantnormals = false;
4984                 if (ent->animcache_svector3f)
4985                         wanttangents = false;
4986                 if (!wantnormals && !wanttangents)
4987                         return false;
4988         }
4989
4990         // check which kind of cache we need to generate
4991         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4992         {
4993                 // cache the skeleton so the vertex shader can use it
4994                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4995                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4996                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4997                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4998                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4999                 // note: this can fail if the buffer is at the grow limit
5000                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5001                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5002         }
5003         else if (ent->animcache_vertex3f)
5004         {
5005                 // mesh was already cached but we may need to add normals/tangents
5006                 // (this only happens with multiple views, reflections, cameras, etc)
5007                 if (wantnormals || wanttangents)
5008                 {
5009                         numvertices = model->surfmesh.num_vertices;
5010                         if (wantnormals)
5011                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5012                         if (wanttangents)
5013                         {
5014                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5015                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5016                         }
5017                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5018                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5019                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5020                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5021                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5022                 }
5023         }
5024         else
5025         {
5026                 // generate mesh cache
5027                 numvertices = model->surfmesh.num_vertices;
5028                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5029                 if (wantnormals)
5030                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5031                 if (wanttangents)
5032                 {
5033                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5034                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5035                 }
5036                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5037                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5038                 if (wantnormals || wanttangents)
5039                 {
5040                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5041                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5042                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5043                 }
5044                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5045                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5046                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5047         }
5048         return true;
5049 }
5050
5051 void R_AnimCache_CacheVisibleEntities(void)
5052 {
5053         int i;
5054         qboolean wantnormals = true;
5055         qboolean wanttangents = !r_showsurfaces.integer;
5056
5057         switch(vid.renderpath)
5058         {
5059         case RENDERPATH_GL20:
5060         case RENDERPATH_D3D9:
5061         case RENDERPATH_D3D10:
5062         case RENDERPATH_D3D11:
5063         case RENDERPATH_GLES2:
5064                 break;
5065         case RENDERPATH_GL11:
5066         case RENDERPATH_GL13:
5067         case RENDERPATH_GLES1:
5068                 wanttangents = false;
5069                 break;
5070         case RENDERPATH_SOFT:
5071                 break;
5072         }
5073
5074         if (r_shownormals.integer)
5075                 wanttangents = wantnormals = true;
5076
5077         // TODO: thread this
5078         // NOTE: R_PrepareRTLights() also caches entities
5079
5080         for (i = 0;i < r_refdef.scene.numentities;i++)
5081                 if (r_refdef.viewcache.entityvisible[i])
5082                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5083 }
5084
5085 //==================================================================================
5086
5087 extern cvar_t r_overheadsprites_pushback;
5088
5089 static void R_View_UpdateEntityLighting (void)
5090 {
5091         int i;
5092         entity_render_t *ent;
5093         vec3_t tempdiffusenormal, avg;
5094         vec_t f, fa, fd, fdd;
5095         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5096
5097         for (i = 0;i < r_refdef.scene.numentities;i++)
5098         {
5099                 ent = r_refdef.scene.entities[i];
5100
5101                 // skip unseen models
5102                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5103                         continue;
5104
5105                 // skip bsp models
5106                 if (ent->model && ent->model == cl.worldmodel)
5107                 {
5108                         // TODO: use modellight for r_ambient settings on world?
5109                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5110                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5111                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5112                         continue;
5113                 }
5114                 
5115                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5116                 {
5117                         // aleady updated by CSQC
5118                         // TODO: force modellight on BSP models in this case?
5119                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5120                 }
5121                 else
5122                 {
5123                         // fetch the lighting from the worldmodel data
5124                         VectorClear(ent->modellight_ambient);
5125                         VectorClear(ent->modellight_diffuse);
5126                         VectorClear(tempdiffusenormal);
5127                         if (ent->flags & RENDER_LIGHT)
5128                         {
5129                                 vec3_t org;
5130                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5131
5132                                 // complete lightning for lit sprites
5133                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5134                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5135                                 {
5136                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5137                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5138                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5139                                 }
5140                                 else
5141                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5142
5143                                 if(ent->flags & RENDER_EQUALIZE)
5144                                 {
5145                                         // first fix up ambient lighting...
5146                                         if(r_equalize_entities_minambient.value > 0)
5147                                         {
5148                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5149                                                 if(fd > 0)
5150                                                 {
5151                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5152                                                         if(fa < r_equalize_entities_minambient.value * fd)
5153                                                         {
5154                                                                 // solve:
5155                                                                 //   fa'/fd' = minambient
5156                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5157                                                                 //   ...
5158                                                                 //   fa' = fd' * minambient
5159                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5160                                                                 //   ...
5161                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5162                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5163                                                                 //   ...
5164                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5165                                                                 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
5166                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5167                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5168                                                         }
5169                                                 }
5170                                         }
5171
5172                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5173                                         {
5174                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5175                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5176                                                 f = fa + 0.25 * fd;
5177                                                 if(f > 0)
5178                                                 {
5179                                                         // adjust brightness and saturation to target
5180                                                         avg[0] = avg[1] = avg[2] = fa / f;
5181                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5182                                                         avg[0] = avg[1] = avg[2] = fd / f;
5183                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5184                                                 }
5185                                         }
5186                                 }
5187                         }
5188                         else // highly rare
5189                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5190                 }
5191
5192                 // move the light direction into modelspace coordinates for lighting code
5193                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5194                 if(VectorLength2(ent->modellight_lightdir) == 0)
5195                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5196                 VectorNormalize(ent->modellight_lightdir);
5197         }
5198 }
5199
5200 #define MAX_LINEOFSIGHTTRACES 64
5201
5202 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5203 {
5204         int i;
5205         vec3_t boxmins, boxmaxs;
5206         vec3_t start;
5207         vec3_t end;
5208         dp_model_t *model = r_refdef.scene.worldmodel;
5209
5210         if (!model || !model->brush.TraceLineOfSight)
5211                 return true;
5212
5213         // expand the box a little
5214         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5215         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5216         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5217         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5218         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5219         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5220
5221         // return true if eye is inside enlarged box
5222         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5223                 return true;
5224
5225         // try center
5226         VectorCopy(eye, start);
5227         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5228         if (model->brush.TraceLineOfSight(model, start, end))
5229                 return true;
5230
5231         // try various random positions
5232         for (i = 0;i < numsamples;i++)
5233         {
5234                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5235                 if (model->brush.TraceLineOfSight(model, start, end))
5236                         return true;
5237         }
5238
5239         return false;
5240 }
5241
5242
5243 static void R_View_UpdateEntityVisible (void)
5244 {
5245         int i;
5246         int renderimask;
5247         int samples;
5248         entity_render_t *ent;
5249
5250         if (r_refdef.envmap || r_fb.water.hideplayer)
5251                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5252         else if (chase_active.integer || r_fb.water.renderingscene)
5253                 renderimask = RENDER_VIEWMODEL;
5254         else
5255                 renderimask = RENDER_EXTERIORMODEL;
5256         if (!r_drawviewmodel.integer)
5257                 renderimask |= RENDER_VIEWMODEL;
5258         if (!r_drawexteriormodel.integer)
5259                 renderimask |= RENDER_EXTERIORMODEL;
5260         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5261         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5262         {
5263                 // worldmodel can check visibility
5264                 for (i = 0;i < r_refdef.scene.numentities;i++)
5265                 {
5266                         ent = r_refdef.scene.entities[i];
5267                         if (!(ent->flags & renderimask))
5268                         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)))
5269                         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))
5270                                 r_refdef.viewcache.entityvisible[i] = true;
5271                 }
5272         }
5273         else
5274         {
5275                 // no worldmodel or it can't check visibility
5276                 for (i = 0;i < r_refdef.scene.numentities;i++)
5277                 {
5278                         ent = r_refdef.scene.entities[i];
5279                         if (!(ent->flags & renderimask))
5280                         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)))
5281                                 r_refdef.viewcache.entityvisible[i] = true;
5282                 }
5283         }
5284         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5285                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5286         {
5287                 for (i = 0;i < r_refdef.scene.numentities;i++)
5288                 {
5289                         if (!r_refdef.viewcache.entityvisible[i])
5290                                 continue;
5291                         ent = r_refdef.scene.entities[i];
5292                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5293                         {
5294                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5295                                 if (samples < 0)
5296                                         continue; // temp entities do pvs only
5297                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5298                                         ent->last_trace_visibility = realtime;
5299                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5300                                         r_refdef.viewcache.entityvisible[i] = 0;
5301                         }
5302                 }
5303         }
5304 }
5305
5306 /// only used if skyrendermasked, and normally returns false
5307 static int R_DrawBrushModelsSky (void)
5308 {
5309         int i, sky;
5310         entity_render_t *ent;
5311
5312         sky = false;
5313         for (i = 0;i < r_refdef.scene.numentities;i++)
5314         {
5315                 if (!r_refdef.viewcache.entityvisible[i])
5316                         continue;
5317                 ent = r_refdef.scene.entities[i];
5318                 if (!ent->model || !ent->model->DrawSky)
5319                         continue;
5320                 ent->model->DrawSky(ent);
5321                 sky = true;
5322         }
5323         return sky;
5324 }
5325
5326 static void R_DrawNoModel(entity_render_t *ent);
5327 static void R_DrawModels(void)
5328 {
5329         int i;
5330         entity_render_t *ent;
5331
5332         for (i = 0;i < r_refdef.scene.numentities;i++)
5333         {
5334                 if (!r_refdef.viewcache.entityvisible[i])
5335                         continue;
5336                 ent = r_refdef.scene.entities[i];
5337                 r_refdef.stats[r_stat_entities]++;
5338                 /*
5339                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5340                 {
5341                         vec3_t f, l, u, o;
5342                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5343                         Con_Printf("R_DrawModels\n");
5344                         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]);
5345                         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);
5346                         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);
5347                 }
5348                 */
5349                 if (ent->model && ent->model->Draw != NULL)
5350                         ent->model->Draw(ent);
5351                 else
5352                         R_DrawNoModel(ent);
5353         }
5354 }
5355
5356 static void R_DrawModelsDepth(void)
5357 {
5358         int i;
5359         entity_render_t *ent;
5360
5361         for (i = 0;i < r_refdef.scene.numentities;i++)
5362         {
5363                 if (!r_refdef.viewcache.entityvisible[i])
5364                         continue;
5365                 ent = r_refdef.scene.entities[i];
5366                 if (ent->model && ent->model->DrawDepth != NULL)
5367                         ent->model->DrawDepth(ent);
5368         }
5369 }
5370
5371 static void R_DrawModelsDebug(void)
5372 {
5373         int i;
5374         entity_render_t *ent;
5375
5376         for (i = 0;i < r_refdef.scene.numentities;i++)
5377         {
5378                 if (!r_refdef.viewcache.entityvisible[i])
5379                         continue;
5380                 ent = r_refdef.scene.entities[i];
5381                 if (ent->model && ent->model->DrawDebug != NULL)
5382                         ent->model->DrawDebug(ent);
5383         }
5384 }
5385
5386 static void R_DrawModelsAddWaterPlanes(void)
5387 {
5388         int i;
5389         entity_render_t *ent;
5390
5391         for (i = 0;i < r_refdef.scene.numentities;i++)
5392         {
5393                 if (!r_refdef.viewcache.entityvisible[i])
5394                         continue;
5395                 ent = r_refdef.scene.entities[i];
5396                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5397                         ent->model->DrawAddWaterPlanes(ent);
5398         }
5399 }
5400
5401 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}};
5402
5403 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5404 {
5405         if (r_hdr_irisadaptation.integer)
5406         {
5407                 vec3_t p;
5408                 vec3_t ambient;
5409                 vec3_t diffuse;
5410                 vec3_t diffusenormal;
5411                 vec3_t forward;
5412                 vec_t brightness = 0.0f;
5413                 vec_t goal;
5414                 vec_t current;
5415                 vec_t d;
5416                 int c;
5417                 VectorCopy(r_refdef.view.forward, forward);
5418                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5419                 {
5420                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5421                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5422                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5423                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5424                         d = DotProduct(forward, diffusenormal);
5425                         brightness += VectorLength(ambient);
5426                         if (d > 0)
5427                                 brightness += d * VectorLength(diffuse);
5428                 }
5429                 brightness *= 1.0f / c;
5430                 brightness += 0.00001f; // make sure it's never zero
5431                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5432                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5433                 current = r_hdr_irisadaptation_value.value;
5434                 if (current < goal)
5435                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5436                 else if (current > goal)
5437                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5438                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5439                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5440         }
5441         else if (r_hdr_irisadaptation_value.value != 1.0f)
5442                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5443 }
5444
5445 static void R_View_SetFrustum(const int *scissor)
5446 {
5447         int i;
5448         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5449         vec3_t forward, left, up, origin, v;
5450
5451         if(scissor)
5452         {
5453                 // flipped x coordinates (because x points left here)
5454                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5455                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5456
5457                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5458                 switch(vid.renderpath)
5459                 {
5460                         case RENDERPATH_D3D9:
5461                         case RENDERPATH_D3D10:
5462                         case RENDERPATH_D3D11:
5463                                 // non-flipped y coordinates
5464                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5465                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5466                                 break;
5467                         case RENDERPATH_SOFT:
5468                         case RENDERPATH_GL11:
5469                         case RENDERPATH_GL13:
5470                         case RENDERPATH_GL20:
5471                         case RENDERPATH_GLES1:
5472                         case RENDERPATH_GLES2:
5473                                 // non-flipped y coordinates
5474                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5475                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5476                                 break;
5477                 }
5478         }
5479
5480         // we can't trust r_refdef.view.forward and friends in reflected scenes
5481         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5482
5483 #if 0
5484         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5485         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5486         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5487         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5488         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5489         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5490         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5491         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5492         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5493         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5494         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5495         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5496 #endif
5497
5498 #if 0
5499         zNear = r_refdef.nearclip;
5500         nudge = 1.0 - 1.0 / (1<<23);
5501         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5502         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5503         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5504         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5505         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5506         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5507         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5508         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5509 #endif
5510
5511
5512
5513 #if 0
5514         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5515         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5516         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5517         r_refdef.view.frustum[0].dist = m[15] - m[12];
5518
5519         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5520         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5521         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5522         r_refdef.view.frustum[1].dist = m[15] + m[12];
5523
5524         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5525         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5526         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5527         r_refdef.view.frustum[2].dist = m[15] - m[13];
5528
5529         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5530         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5531         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5532         r_refdef.view.frustum[3].dist = m[15] + m[13];
5533
5534         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5535         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5536         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5537         r_refdef.view.frustum[4].dist = m[15] - m[14];
5538
5539         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5540         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5541         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5542         r_refdef.view.frustum[5].dist = m[15] + m[14];
5543 #endif
5544
5545         if (r_refdef.view.useperspective)
5546         {
5547                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5548                 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]);
5549                 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]);
5550                 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]);
5551                 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]);
5552
5553                 // then the normals from the corners relative to origin
5554                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5555                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5556                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5557                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5558
5559                 // in a NORMAL view, forward cross left == up
5560                 // in a REFLECTED view, forward cross left == down
5561                 // so our cross products above need to be adjusted for a left handed coordinate system
5562                 CrossProduct(forward, left, v);
5563                 if(DotProduct(v, up) < 0)
5564                 {
5565                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5566                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5567                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5568                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5569                 }
5570
5571                 // Leaving those out was a mistake, those were in the old code, and they
5572                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5573                 // I couldn't reproduce it after adding those normalizations. --blub
5574                 VectorNormalize(r_refdef.view.frustum[0].normal);
5575                 VectorNormalize(r_refdef.view.frustum[1].normal);
5576                 VectorNormalize(r_refdef.view.frustum[2].normal);
5577                 VectorNormalize(r_refdef.view.frustum[3].normal);
5578
5579                 // make the corners absolute
5580                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5581                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5582                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5583                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5584
5585                 // one more normal
5586                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5587
5588                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5589                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5590                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5591                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5592                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5593         }
5594         else
5595         {
5596                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5597                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5598                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5599                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5600                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5601                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5602                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5603                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5604                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5605                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5606         }
5607         r_refdef.view.numfrustumplanes = 5;
5608
5609         if (r_refdef.view.useclipplane)
5610         {
5611                 r_refdef.view.numfrustumplanes = 6;
5612                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5613         }
5614
5615         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5616                 PlaneClassify(r_refdef.view.frustum + i);
5617
5618         // LordHavoc: note to all quake engine coders, Quake had a special case
5619         // for 90 degrees which assumed a square view (wrong), so I removed it,
5620         // Quake2 has it disabled as well.
5621
5622         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5623         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5624         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5625         //PlaneClassify(&frustum[0]);
5626
5627         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5628         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5629         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5630         //PlaneClassify(&frustum[1]);
5631
5632         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5633         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5634         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5635         //PlaneClassify(&frustum[2]);
5636
5637         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5638         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5639         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5640         //PlaneClassify(&frustum[3]);
5641
5642         // nearclip plane
5643         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5644         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5645         //PlaneClassify(&frustum[4]);
5646 }
5647
5648 static void R_View_UpdateWithScissor(const int *myscissor)
5649 {
5650         R_Main_ResizeViewCache();
5651         R_View_SetFrustum(myscissor);
5652         R_View_WorldVisibility(r_refdef.view.useclipplane);
5653         R_View_UpdateEntityVisible();
5654         R_View_UpdateEntityLighting();
5655 }
5656
5657 static void R_View_Update(void)
5658 {
5659         R_Main_ResizeViewCache();
5660         R_View_SetFrustum(NULL);
5661         R_View_WorldVisibility(r_refdef.view.useclipplane);
5662         R_View_UpdateEntityVisible();
5663         R_View_UpdateEntityLighting();
5664 }
5665
5666 float viewscalefpsadjusted = 1.0f;
5667
5668 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5669 {
5670         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5671         scale = bound(0.03125f, scale, 1.0f);
5672         *outwidth = (int)ceil(width * scale);
5673         *outheight = (int)ceil(height * scale);
5674 }
5675
5676 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5677 {
5678         const float *customclipplane = NULL;
5679         float plane[4];
5680         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5681         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5682         {
5683                 // LordHavoc: couldn't figure out how to make this approach the
5684                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5685                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5686                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5687                         dist = r_refdef.view.clipplane.dist;
5688                 plane[0] = r_refdef.view.clipplane.normal[0];
5689                 plane[1] = r_refdef.view.clipplane.normal[1];
5690                 plane[2] = r_refdef.view.clipplane.normal[2];
5691                 plane[3] = -dist;
5692                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5693         }
5694
5695         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5696         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5697
5698         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5699         if (!r_refdef.view.useperspective)
5700                 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);
5701         else if (vid.stencil && r_useinfinitefarclip.integer)
5702                 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);
5703         else
5704                 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);
5705         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5706         R_SetViewport(&r_refdef.view.viewport);
5707         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5708         {
5709                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5710                 float screenplane[4];
5711                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5712                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5713                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5714                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5715                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5716         }
5717 }
5718
5719 void R_EntityMatrix(const matrix4x4_t *matrix)
5720 {
5721         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5722         {
5723                 gl_modelmatrixchanged = false;
5724                 gl_modelmatrix = *matrix;
5725                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5726                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5727                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5728                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5729                 CHECKGLERROR
5730                 switch(vid.renderpath)
5731                 {
5732                 case RENDERPATH_D3D9:
5733 #ifdef SUPPORTD3D
5734                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5735                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5736 #endif
5737                         break;
5738                 case RENDERPATH_D3D10:
5739                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5740                         break;
5741                 case RENDERPATH_D3D11:
5742                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5743                         break;
5744                 case RENDERPATH_GL11:
5745                 case RENDERPATH_GL13:
5746                 case RENDERPATH_GLES1:
5747 #ifndef USE_GLES2
5748                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5749 #endif
5750                         break;
5751                 case RENDERPATH_SOFT:
5752                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5753                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5754                         break;
5755                 case RENDERPATH_GL20:
5756                 case RENDERPATH_GLES2:
5757                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5758                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5759                         break;
5760                 }
5761         }
5762 }
5763
5764 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5765 {
5766         r_viewport_t viewport;
5767
5768         CHECKGLERROR
5769
5770         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5771         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);
5772         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5773         R_SetViewport(&viewport);
5774         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5775         GL_Color(1, 1, 1, 1);
5776         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5777         GL_BlendFunc(GL_ONE, GL_ZERO);
5778         GL_ScissorTest(false);
5779         GL_DepthMask(false);
5780         GL_DepthRange(0, 1);
5781         GL_DepthTest(false);
5782         GL_DepthFunc(GL_LEQUAL);
5783         R_EntityMatrix(&identitymatrix);
5784         R_Mesh_ResetTextureState();
5785         GL_PolygonOffset(0, 0);
5786         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5787         switch(vid.renderpath)
5788         {
5789         case RENDERPATH_GL11:
5790         case RENDERPATH_GL13:
5791         case RENDERPATH_GL20:
5792         case RENDERPATH_GLES1:
5793         case RENDERPATH_GLES2:
5794                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5795                 break;
5796         case RENDERPATH_D3D9:
5797         case RENDERPATH_D3D10:
5798         case RENDERPATH_D3D11:
5799         case RENDERPATH_SOFT:
5800                 break;
5801         }
5802         GL_CullFace(GL_NONE);
5803
5804         CHECKGLERROR
5805 }
5806
5807 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5808 {
5809         DrawQ_Finish();
5810
5811         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5812 }
5813
5814 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5815 {
5816         DrawQ_Finish();
5817
5818         R_SetupView(true, fbo, depthtexture, colortexture);
5819         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5820         GL_Color(1, 1, 1, 1);
5821         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5822         GL_BlendFunc(GL_ONE, GL_ZERO);
5823         GL_ScissorTest(true);
5824         GL_DepthMask(true);
5825         GL_DepthRange(0, 1);
5826         GL_DepthTest(true);
5827         GL_DepthFunc(GL_LEQUAL);
5828         R_EntityMatrix(&identitymatrix);
5829         R_Mesh_ResetTextureState();
5830         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5831         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5832         switch(vid.renderpath)
5833         {
5834         case RENDERPATH_GL11:
5835         case RENDERPATH_GL13:
5836         case RENDERPATH_GL20:
5837         case RENDERPATH_GLES1:
5838         case RENDERPATH_GLES2:
5839                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5840                 break;
5841         case RENDERPATH_D3D9:
5842         case RENDERPATH_D3D10:
5843         case RENDERPATH_D3D11:
5844         case RENDERPATH_SOFT:
5845                 break;
5846         }
5847         GL_CullFace(r_refdef.view.cullface_back);
5848 }
5849
5850 /*
5851 ================
5852 R_RenderView_UpdateViewVectors
5853 ================
5854 */
5855 void R_RenderView_UpdateViewVectors(void)
5856 {
5857         // break apart the view matrix into vectors for various purposes
5858         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5859         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5860         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5861         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5862         // make an inverted copy of the view matrix for tracking sprites
5863         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5864 }
5865
5866 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5867 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5868
5869 static void R_Water_StartFrame(void)
5870 {
5871         int i;
5872         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5873         r_waterstate_waterplane_t *p;
5874         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;
5875
5876         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5877                 return;
5878
5879         switch(vid.renderpath)
5880         {
5881         case RENDERPATH_GL20:
5882         case RENDERPATH_D3D9:
5883         case RENDERPATH_D3D10:
5884         case RENDERPATH_D3D11:
5885         case RENDERPATH_SOFT:
5886         case RENDERPATH_GLES2:
5887                 break;
5888         case RENDERPATH_GL11:
5889         case RENDERPATH_GL13:
5890         case RENDERPATH_GLES1:
5891                 return;
5892         }
5893
5894         // set waterwidth and waterheight to the water resolution that will be
5895         // used (often less than the screen resolution for faster rendering)
5896         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5897
5898         // calculate desired texture sizes
5899         // can't use water if the card does not support the texture size
5900         if (!r_water.integer || r_showsurfaces.integer)
5901                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5902         else if (vid.support.arb_texture_non_power_of_two)
5903         {
5904                 texturewidth = waterwidth;
5905                 textureheight = waterheight;
5906                 camerawidth = waterwidth;
5907                 cameraheight = waterheight;
5908         }
5909         else
5910         {
5911                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5912                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5913                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5914                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5915         }
5916
5917         // allocate textures as needed
5918         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))
5919         {
5920                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5921                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5922                 {
5923                         if (p->texture_refraction)
5924                                 R_FreeTexture(p->texture_refraction);
5925                         p->texture_refraction = NULL;
5926                         if (p->fbo_refraction)
5927                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5928                         p->fbo_refraction = 0;
5929                         if (p->texture_reflection)
5930                                 R_FreeTexture(p->texture_reflection);
5931                         p->texture_reflection = NULL;
5932                         if (p->fbo_reflection)
5933                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5934                         p->fbo_reflection = 0;
5935                         if (p->texture_camera)
5936                                 R_FreeTexture(p->texture_camera);
5937                         p->texture_camera = NULL;
5938                         if (p->fbo_camera)
5939                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5940                         p->fbo_camera = 0;
5941                 }
5942                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5943                 r_fb.water.texturewidth = texturewidth;
5944                 r_fb.water.textureheight = textureheight;
5945                 r_fb.water.camerawidth = camerawidth;
5946                 r_fb.water.cameraheight = cameraheight;
5947         }
5948
5949         if (r_fb.water.texturewidth)
5950         {
5951                 int scaledwidth, scaledheight;
5952
5953                 r_fb.water.enabled = true;
5954
5955                 // water resolution is usually reduced
5956                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5957                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5958                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5959
5960                 // set up variables that will be used in shader setup
5961                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5962                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5963                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5964                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5965         }
5966
5967         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5968         r_fb.water.numwaterplanes = 0;
5969 }
5970
5971 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5972 {
5973         int planeindex, bestplaneindex, vertexindex;
5974         vec3_t mins, maxs, normal, center, v, n;
5975         vec_t planescore, bestplanescore;
5976         mplane_t plane;
5977         r_waterstate_waterplane_t *p;
5978         texture_t *t = R_GetCurrentTexture(surface->texture);
5979
5980         rsurface.texture = t;
5981         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5982         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5983         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5984                 return;
5985         // average the vertex normals, find the surface bounds (after deformvertexes)
5986         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5987         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5988         VectorCopy(n, normal);
5989         VectorCopy(v, mins);
5990         VectorCopy(v, maxs);
5991         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5992         {
5993                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5994                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5995                 VectorAdd(normal, n, normal);
5996                 mins[0] = min(mins[0], v[0]);
5997                 mins[1] = min(mins[1], v[1]);
5998                 mins[2] = min(mins[2], v[2]);
5999                 maxs[0] = max(maxs[0], v[0]);
6000                 maxs[1] = max(maxs[1], v[1]);
6001                 maxs[2] = max(maxs[2], v[2]);
6002         }
6003         VectorNormalize(normal);
6004         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6005
6006         VectorCopy(normal, plane.normal);
6007         VectorNormalize(plane.normal);
6008         plane.dist = DotProduct(center, plane.normal);
6009         PlaneClassify(&plane);
6010         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6011         {
6012                 // skip backfaces (except if nocullface is set)
6013 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6014 //                      return;
6015                 VectorNegate(plane.normal, plane.normal);
6016                 plane.dist *= -1;
6017                 PlaneClassify(&plane);
6018         }
6019
6020
6021         // find a matching plane if there is one
6022         bestplaneindex = -1;
6023         bestplanescore = 1048576.0f;
6024         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6025         {
6026                 if(p->camera_entity == t->camera_entity)
6027                 {
6028                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6029                         if (bestplaneindex < 0 || bestplanescore > planescore)
6030                         {
6031                                 bestplaneindex = planeindex;
6032                                 bestplanescore = planescore;
6033                         }
6034                 }
6035         }
6036         planeindex = bestplaneindex;
6037
6038         // if this surface does not fit any known plane rendered this frame, add one
6039         if (planeindex < 0 || bestplanescore > 0.001f)
6040         {
6041                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6042                 {
6043                         // store the new plane
6044                         planeindex = r_fb.water.numwaterplanes++;
6045                         p = r_fb.water.waterplanes + planeindex;
6046                         p->plane = plane;
6047                         // clear materialflags and pvs
6048                         p->materialflags = 0;
6049                         p->pvsvalid = false;
6050                         p->camera_entity = t->camera_entity;
6051                         VectorCopy(mins, p->mins);
6052                         VectorCopy(maxs, p->maxs);
6053                 }
6054                 else
6055                 {
6056                         // We're totally screwed.
6057                         return;
6058                 }
6059         }
6060         else
6061         {
6062                 // merge mins/maxs when we're adding this surface to the plane
6063                 p = r_fb.water.waterplanes + planeindex;
6064                 p->mins[0] = min(p->mins[0], mins[0]);
6065                 p->mins[1] = min(p->mins[1], mins[1]);
6066                 p->mins[2] = min(p->mins[2], mins[2]);
6067                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6068                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6069                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6070         }
6071         // merge this surface's materialflags into the waterplane
6072         p->materialflags |= t->currentmaterialflags;
6073         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6074         {
6075                 // merge this surface's PVS into the waterplane
6076                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6077                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6078                 {
6079                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6080                         p->pvsvalid = true;
6081                 }
6082         }
6083 }
6084
6085 extern cvar_t r_drawparticles;
6086 extern cvar_t r_drawdecals;
6087
6088 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6089 {
6090         int myscissor[4];
6091         r_refdef_view_t originalview;
6092         r_refdef_view_t myview;
6093         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;
6094         r_waterstate_waterplane_t *p;
6095         vec3_t visorigin;
6096         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;
6097         char vabuf[1024];
6098
6099         originalview = r_refdef.view;
6100
6101         // lowquality hack, temporarily shut down some cvars and restore afterwards
6102         qualityreduction = r_water_lowquality.integer;
6103         if (qualityreduction > 0)
6104         {
6105                 if (qualityreduction >= 1)
6106                 {
6107                         old_r_shadows = r_shadows.integer;
6108                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6109                         old_r_dlight = r_shadow_realtime_dlight.integer;
6110                         Cvar_SetValueQuick(&r_shadows, 0);
6111                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6112                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6113                 }
6114                 if (qualityreduction >= 2)
6115                 {
6116                         old_r_dynamic = r_dynamic.integer;
6117                         old_r_particles = r_drawparticles.integer;
6118                         old_r_decals = r_drawdecals.integer;
6119                         Cvar_SetValueQuick(&r_dynamic, 0);
6120                         Cvar_SetValueQuick(&r_drawparticles, 0);
6121                         Cvar_SetValueQuick(&r_drawdecals, 0);
6122                 }
6123         }
6124
6125         // make sure enough textures are allocated
6126         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6127         {
6128                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6129                         continue;
6130                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6131                 {
6132                         if (!p->texture_refraction)
6133                                 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);
6134                         if (!p->texture_refraction)
6135                                 goto error;
6136                         if (usewaterfbo)
6137                         {
6138                                 if (r_fb.water.depthtexture == NULL)
6139                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6140                                 if (p->fbo_refraction == 0)
6141                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6142                         }
6143                 }
6144                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6145                 {
6146                         if (!p->texture_camera)
6147                                 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);
6148                         if (!p->texture_camera)
6149                                 goto error;
6150                         if (usewaterfbo)
6151                         {
6152                                 if (r_fb.water.depthtexture == NULL)
6153                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6154                                 if (p->fbo_camera == 0)
6155                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6156                         }
6157                 }
6158
6159                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6160                 {
6161                         if (!p->texture_reflection)
6162                                 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);
6163                         if (!p->texture_reflection)
6164                                 goto error;
6165                         if (usewaterfbo)
6166                         {
6167                                 if (r_fb.water.depthtexture == NULL)
6168                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6169                                 if (p->fbo_reflection == 0)
6170                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6171                         }
6172                 }
6173         }
6174
6175         // render views
6176         r_refdef.view = originalview;
6177         r_refdef.view.showdebug = false;
6178         r_refdef.view.width = r_fb.water.waterwidth;
6179         r_refdef.view.height = r_fb.water.waterheight;
6180         r_refdef.view.useclipplane = true;
6181         myview = r_refdef.view;
6182         r_fb.water.renderingscene = true;
6183         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6184         {
6185                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6186                         continue;
6187                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6188                 {
6189                         r_refdef.view = myview;
6190                         if(r_water_scissormode.integer)
6191                         {
6192                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6193                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6194                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6195                         }
6196
6197                         // render reflected scene and copy into texture
6198                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6199                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6200                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6201                         r_refdef.view.clipplane = p->plane;
6202                         // reverse the cullface settings for this render
6203                         r_refdef.view.cullface_front = GL_FRONT;
6204                         r_refdef.view.cullface_back = GL_BACK;
6205                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6206                         {
6207                                 r_refdef.view.usecustompvs = true;
6208                                 if (p->pvsvalid)
6209                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6210                                 else
6211                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6212                         }
6213
6214                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6215                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6216                         R_ClearScreen(r_refdef.fogenabled);
6217                         if(r_water_scissormode.integer & 2)
6218                                 R_View_UpdateWithScissor(myscissor);
6219                         else
6220                                 R_View_Update();
6221                         R_AnimCache_CacheVisibleEntities();
6222                         if(r_water_scissormode.integer & 1)
6223                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6224                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6225
6226                         if (!p->fbo_reflection)
6227                                 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);
6228                         r_fb.water.hideplayer = false;
6229                 }
6230
6231                 // render the normal view scene and copy into texture
6232                 // (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)
6233                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6234                 {
6235                         r_refdef.view = myview;
6236                         if(r_water_scissormode.integer)
6237                         {
6238                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6239                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6240                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6241                         }
6242
6243                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6244
6245                         r_refdef.view.clipplane = p->plane;
6246                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6247                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6248
6249                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6250                         {
6251                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6252                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6253                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6254                                 R_RenderView_UpdateViewVectors();
6255                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6256                                 {
6257                                         r_refdef.view.usecustompvs = true;
6258                                         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);
6259                                 }
6260                         }
6261
6262                         PlaneClassify(&r_refdef.view.clipplane);
6263
6264                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6265                         R_ClearScreen(r_refdef.fogenabled);
6266                         if(r_water_scissormode.integer & 2)
6267                                 R_View_UpdateWithScissor(myscissor);
6268                         else
6269                                 R_View_Update();
6270                         R_AnimCache_CacheVisibleEntities();
6271                         if(r_water_scissormode.integer & 1)
6272                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6273                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6274
6275                         if (!p->fbo_refraction)
6276                                 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);
6277                         r_fb.water.hideplayer = false;
6278                 }
6279                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6280                 {
6281                         r_refdef.view = myview;
6282
6283                         r_refdef.view.clipplane = p->plane;
6284                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6285                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6286
6287                         r_refdef.view.width = r_fb.water.camerawidth;
6288                         r_refdef.view.height = r_fb.water.cameraheight;
6289                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6290                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6291                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6292                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6293
6294                         if(p->camera_entity)
6295                         {
6296                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6297                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6298                         }
6299
6300                         // note: all of the view is used for displaying... so
6301                         // there is no use in scissoring
6302
6303                         // reverse the cullface settings for this render
6304                         r_refdef.view.cullface_front = GL_FRONT;
6305                         r_refdef.view.cullface_back = GL_BACK;
6306                         // also reverse the view matrix
6307                         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
6308                         R_RenderView_UpdateViewVectors();
6309                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6310                         {
6311                                 r_refdef.view.usecustompvs = true;
6312                                 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);
6313                         }
6314                         
6315                         // camera needs no clipplane
6316                         r_refdef.view.useclipplane = false;
6317
6318                         PlaneClassify(&r_refdef.view.clipplane);
6319
6320                         r_fb.water.hideplayer = false;
6321
6322                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6323                         R_ClearScreen(r_refdef.fogenabled);
6324                         R_View_Update();
6325                         R_AnimCache_CacheVisibleEntities();
6326                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6327
6328                         if (!p->fbo_camera)
6329                                 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);
6330                         r_fb.water.hideplayer = false;
6331                 }
6332
6333         }
6334         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6335         r_fb.water.renderingscene = false;
6336         r_refdef.view = originalview;
6337         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6338         if (!r_fb.water.depthtexture)
6339                 R_ClearScreen(r_refdef.fogenabled);
6340         R_View_Update();
6341         R_AnimCache_CacheVisibleEntities();
6342         goto finish;
6343 error:
6344         r_refdef.view = originalview;
6345         r_fb.water.renderingscene = false;
6346         Cvar_SetValueQuick(&r_water, 0);
6347         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6348 finish:
6349         // lowquality hack, restore cvars
6350         if (qualityreduction > 0)
6351         {
6352                 if (qualityreduction >= 1)
6353                 {
6354                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6355                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6356                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6357                 }
6358                 if (qualityreduction >= 2)
6359                 {
6360                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6361                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6362                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6363                 }
6364         }
6365 }
6366
6367 static void R_Bloom_StartFrame(void)
6368 {
6369         int i;
6370         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6371         int viewwidth, viewheight;
6372         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6373         textype_t textype = TEXTYPE_COLORBUFFER;
6374
6375         switch (vid.renderpath)
6376         {
6377         case RENDERPATH_GL20:
6378                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6379                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6380                 {
6381                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6382                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6383                 }
6384                 break;
6385         case RENDERPATH_GL11:
6386         case RENDERPATH_GL13:
6387         case RENDERPATH_GLES1:
6388         case RENDERPATH_GLES2:
6389         case RENDERPATH_D3D9:
6390         case RENDERPATH_D3D10:
6391         case RENDERPATH_D3D11:
6392                 r_fb.usedepthtextures = false;
6393                 break;
6394         case RENDERPATH_SOFT:
6395                 r_fb.usedepthtextures = true;
6396                 break;
6397         }
6398
6399         if (r_viewscale_fpsscaling.integer)
6400         {
6401                 double actualframetime;
6402                 double targetframetime;
6403                 double adjust;
6404                 actualframetime = r_refdef.lastdrawscreentime;
6405                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6406                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6407                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6408                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6409                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6410                 viewscalefpsadjusted += adjust;
6411                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6412         }
6413         else
6414                 viewscalefpsadjusted = 1.0f;
6415
6416         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6417
6418         switch(vid.renderpath)
6419         {
6420         case RENDERPATH_GL20:
6421         case RENDERPATH_D3D9:
6422         case RENDERPATH_D3D10:
6423         case RENDERPATH_D3D11:
6424         case RENDERPATH_SOFT:
6425         case RENDERPATH_GLES2:
6426                 break;
6427         case RENDERPATH_GL11:
6428         case RENDERPATH_GL13:
6429         case RENDERPATH_GLES1:
6430                 return;
6431         }
6432
6433         // set bloomwidth and bloomheight to the bloom resolution that will be
6434         // used (often less than the screen resolution for faster rendering)
6435         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6436         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6437         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6438         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6439         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6440
6441         // calculate desired texture sizes
6442         if (vid.support.arb_texture_non_power_of_two)
6443         {
6444                 screentexturewidth = vid.width;
6445                 screentextureheight = vid.height;
6446                 bloomtexturewidth = r_fb.bloomwidth;
6447                 bloomtextureheight = r_fb.bloomheight;
6448         }
6449         else
6450         {
6451                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6452                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6453                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6454                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6455         }
6456
6457         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))
6458         {
6459                 Cvar_SetValueQuick(&r_bloom, 0);
6460                 Cvar_SetValueQuick(&r_motionblur, 0);
6461                 Cvar_SetValueQuick(&r_damageblur, 0);
6462         }
6463
6464         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6465          && !r_bloom.integer
6466          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6467          && !useviewfbo
6468          && r_viewscale.value == 1.0f
6469          && !r_viewscale_fpsscaling.integer)
6470                 screentexturewidth = screentextureheight = 0;
6471         if (!r_bloom.integer)
6472                 bloomtexturewidth = bloomtextureheight = 0;
6473
6474         // allocate textures as needed
6475         if (r_fb.screentexturewidth != screentexturewidth
6476          || r_fb.screentextureheight != screentextureheight
6477          || r_fb.bloomtexturewidth != bloomtexturewidth
6478          || r_fb.bloomtextureheight != bloomtextureheight
6479          || r_fb.textype != textype
6480          || useviewfbo != (r_fb.fbo != 0))
6481         {
6482                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6483                 {
6484                         if (r_fb.bloomtexture[i])
6485                                 R_FreeTexture(r_fb.bloomtexture[i]);
6486                         r_fb.bloomtexture[i] = NULL;
6487
6488                         if (r_fb.bloomfbo[i])
6489                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6490                         r_fb.bloomfbo[i] = 0;
6491                 }
6492
6493                 if (r_fb.fbo)
6494                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6495                 r_fb.fbo = 0;
6496
6497                 if (r_fb.colortexture)
6498                         R_FreeTexture(r_fb.colortexture);
6499                 r_fb.colortexture = NULL;
6500
6501                 if (r_fb.depthtexture)
6502                         R_FreeTexture(r_fb.depthtexture);
6503                 r_fb.depthtexture = NULL;
6504
6505                 if (r_fb.ghosttexture)
6506                         R_FreeTexture(r_fb.ghosttexture);
6507                 r_fb.ghosttexture = NULL;
6508
6509                 r_fb.screentexturewidth = screentexturewidth;
6510                 r_fb.screentextureheight = screentextureheight;
6511                 r_fb.bloomtexturewidth = bloomtexturewidth;
6512                 r_fb.bloomtextureheight = bloomtextureheight;
6513                 r_fb.textype = textype;
6514
6515                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6516                 {
6517                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6518                                 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);
6519                         r_fb.ghosttexture_valid = false;
6520                         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);
6521                         if (useviewfbo)
6522                         {
6523                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6524                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6525                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6526                         }
6527                 }
6528
6529                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6530                 {
6531                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6532                         {
6533                                 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);
6534                                 if (useviewfbo)
6535                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6536                         }
6537                 }
6538         }
6539
6540         // bloom texture is a different resolution
6541         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6542         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6543         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6544         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6545         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6546
6547         // set up a texcoord array for the full resolution screen image
6548         // (we have to keep this around to copy back during final render)
6549         r_fb.screentexcoord2f[0] = 0;
6550         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6551         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6552         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6553         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6554         r_fb.screentexcoord2f[5] = 0;
6555         r_fb.screentexcoord2f[6] = 0;
6556         r_fb.screentexcoord2f[7] = 0;
6557
6558         if(r_fb.fbo) 
6559         {
6560                 for (i = 1;i < 8;i += 2)
6561                 {
6562                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6563                 }
6564         }
6565
6566         // set up a texcoord array for the reduced resolution bloom image
6567         // (which will be additive blended over the screen image)
6568         r_fb.bloomtexcoord2f[0] = 0;
6569         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6570         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6571         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6572         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6573         r_fb.bloomtexcoord2f[5] = 0;
6574         r_fb.bloomtexcoord2f[6] = 0;
6575         r_fb.bloomtexcoord2f[7] = 0;
6576
6577         switch(vid.renderpath)
6578         {
6579         case RENDERPATH_GL11:
6580         case RENDERPATH_GL13:
6581         case RENDERPATH_GL20:
6582         case RENDERPATH_SOFT:
6583         case RENDERPATH_GLES1:
6584         case RENDERPATH_GLES2:
6585                 break;
6586         case RENDERPATH_D3D9:
6587         case RENDERPATH_D3D10:
6588         case RENDERPATH_D3D11:
6589                 for (i = 0;i < 4;i++)
6590                 {
6591                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6592                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6593                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6594                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6595                 }
6596                 break;
6597         }
6598
6599         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6600
6601         if (r_fb.fbo)
6602                 r_refdef.view.clear = true;
6603 }
6604
6605 static void R_Bloom_MakeTexture(void)
6606 {
6607         int x, range, dir;
6608         float xoffset, yoffset, r, brighten;
6609         rtexture_t *intex;
6610         float colorscale = r_bloom_colorscale.value;
6611
6612         r_refdef.stats[r_stat_bloom]++;
6613     
6614 #if 0
6615     // this copy is unnecessary since it happens in R_BlendView already
6616         if (!r_fb.fbo)
6617         {
6618                 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);
6619                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6620         }
6621 #endif
6622
6623         // scale down screen texture to the bloom texture size
6624         CHECKGLERROR
6625         r_fb.bloomindex = 0;
6626         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6627         R_SetViewport(&r_fb.bloomviewport);
6628         GL_CullFace(GL_NONE);
6629         GL_DepthTest(false);
6630         GL_BlendFunc(GL_ONE, GL_ZERO);
6631         GL_Color(colorscale, colorscale, colorscale, 1);
6632         // 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...
6633         switch(vid.renderpath)
6634         {
6635         case RENDERPATH_GL11:
6636         case RENDERPATH_GL13:
6637         case RENDERPATH_GL20:
6638         case RENDERPATH_GLES1:
6639         case RENDERPATH_GLES2:
6640         case RENDERPATH_SOFT:
6641                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6642                 break;
6643         case RENDERPATH_D3D9:
6644         case RENDERPATH_D3D10:
6645         case RENDERPATH_D3D11:
6646                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6647                 break;
6648         }
6649         // TODO: do boxfilter scale-down in shader?
6650         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6651         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6652         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6653
6654         // we now have a properly scaled bloom image
6655         if (!r_fb.bloomfbo[r_fb.bloomindex])
6656         {
6657                 // copy it into the bloom texture
6658                 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);
6659                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6660         }
6661
6662         // multiply bloom image by itself as many times as desired
6663         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6664         {
6665                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6666                 r_fb.bloomindex ^= 1;
6667                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6668                 x *= 2;
6669                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6670                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6671                 {
6672                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6673                         GL_Color(r,r,r,1); // apply fix factor
6674                 }
6675                 else
6676                 {
6677                         if(x <= 2)
6678                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6679                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6680                         GL_Color(1,1,1,1); // no fix factor supported here
6681                 }
6682                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6683                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6684                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6685                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6686
6687                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6688                 {
6689                         // copy the darkened image to a texture
6690                         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);
6691                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6692                 }
6693         }
6694
6695         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6696         brighten = r_bloom_brighten.value;
6697         brighten = sqrt(brighten);
6698         if(range >= 1)
6699                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6700
6701         for (dir = 0;dir < 2;dir++)
6702         {
6703                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6704                 r_fb.bloomindex ^= 1;
6705                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6706                 // blend on at multiple vertical offsets to achieve a vertical blur
6707                 // TODO: do offset blends using GLSL
6708                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6709                 GL_BlendFunc(GL_ONE, GL_ZERO);
6710                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6711                 for (x = -range;x <= range;x++)
6712                 {
6713                         if (!dir){xoffset = 0;yoffset = x;}
6714                         else {xoffset = x;yoffset = 0;}
6715                         xoffset /= (float)r_fb.bloomtexturewidth;
6716                         yoffset /= (float)r_fb.bloomtextureheight;
6717                         // compute a texcoord array with the specified x and y offset
6718                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6719                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6720                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6721                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6722                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6723                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6724                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6725                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6726                         // this r value looks like a 'dot' particle, fading sharply to
6727                         // black at the edges
6728                         // (probably not realistic but looks good enough)
6729                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6730                         //r = brighten/(range*2+1);
6731                         r = brighten / (range * 2 + 1);
6732                         if(range >= 1)
6733                                 r *= (1 - x*x/(float)(range*range));
6734                         GL_Color(r, r, r, 1);
6735                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6736                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6737                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6738                         GL_BlendFunc(GL_ONE, GL_ONE);
6739                 }
6740
6741                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6742                 {
6743                         // copy the vertically or horizontally blurred bloom view to a texture
6744                         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);
6745                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6746                 }
6747         }
6748 }
6749
6750 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6751 {
6752         unsigned int permutation;
6753         float uservecs[4][4];
6754
6755         R_EntityMatrix(&identitymatrix);
6756
6757         switch (vid.renderpath)
6758         {
6759         case RENDERPATH_GL20:
6760         case RENDERPATH_D3D9:
6761         case RENDERPATH_D3D10:
6762         case RENDERPATH_D3D11:
6763         case RENDERPATH_SOFT:
6764         case RENDERPATH_GLES2:
6765                 permutation =
6766                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6767                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6768                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6769                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6770                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6771
6772                 if (r_fb.colortexture)
6773                 {
6774                         if (!r_fb.fbo)
6775                         {
6776                                 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);
6777                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6778                         }
6779
6780                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6781                         {
6782                                 // declare variables
6783                                 float blur_factor, blur_mouseaccel, blur_velocity;
6784                                 static float blur_average; 
6785                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6786
6787                                 // set a goal for the factoring
6788                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6789                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6790                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6791                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6792                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6793                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6794
6795                                 // from the goal, pick an averaged value between goal and last value
6796                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6797                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6798
6799                                 // enforce minimum amount of blur 
6800                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6801
6802                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6803
6804                                 // calculate values into a standard alpha
6805                                 cl.motionbluralpha = 1 - exp(-
6806                                                 (
6807                                                  (r_motionblur.value * blur_factor / 80)
6808                                                  +
6809                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6810                                                 )
6811                                                 /
6812                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6813                                           );
6814
6815                                 // randomization for the blur value to combat persistent ghosting
6816                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6817                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6818
6819                                 // apply the blur
6820                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6821                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6822                                 {
6823                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6824                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6825                                         switch(vid.renderpath)
6826                                         {
6827                                         case RENDERPATH_GL11:
6828                                         case RENDERPATH_GL13:
6829                                         case RENDERPATH_GL20:
6830                                         case RENDERPATH_GLES1:
6831                                         case RENDERPATH_GLES2:
6832                                         case RENDERPATH_SOFT:
6833                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6834                                                 break;
6835                                         case RENDERPATH_D3D9:
6836                                         case RENDERPATH_D3D10:
6837                                         case RENDERPATH_D3D11:
6838                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6839                                                 break;
6840                                         }
6841                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6842                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6843                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6844                                 }
6845
6846                                 // updates old view angles for next pass
6847                                 VectorCopy(cl.viewangles, blur_oldangles);
6848
6849                                 // copy view into the ghost texture
6850                                 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);
6851                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6852                                 r_fb.ghosttexture_valid = true;
6853                         }
6854                 }
6855                 else
6856                 {
6857                         // no r_fb.colortexture means we're rendering to the real fb
6858                         // we may still have to do view tint...
6859                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6860                         {
6861                                 // apply a color tint to the whole view
6862                                 R_ResetViewRendering2D(0, NULL, NULL);
6863                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865                                 R_SetupShader_Generic_NoTexture(false, true);
6866                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6868                         }
6869                         break; // no screen processing, no bloom, skip it
6870                 }
6871
6872                 if (r_fb.bloomtexture[0])
6873                 {
6874                         // make the bloom texture
6875                         R_Bloom_MakeTexture();
6876                 }
6877
6878 #if _MSC_VER >= 1400
6879 #define sscanf sscanf_s
6880 #endif
6881                 memset(uservecs, 0, sizeof(uservecs));
6882                 if (r_glsl_postprocess_uservec1_enable.integer)
6883                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6884                 if (r_glsl_postprocess_uservec2_enable.integer)
6885                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6886                 if (r_glsl_postprocess_uservec3_enable.integer)
6887                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6888                 if (r_glsl_postprocess_uservec4_enable.integer)
6889                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6890
6891                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6892                 GL_Color(1, 1, 1, 1);
6893                 GL_BlendFunc(GL_ONE, GL_ZERO);
6894
6895                 switch(vid.renderpath)
6896                 {
6897                 case RENDERPATH_GL20:
6898                 case RENDERPATH_GLES2:
6899                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6900                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6901                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6902                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6903                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6904                         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]);
6905                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6906                         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]);
6907                         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]);
6908                         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]);
6909                         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]);
6910                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6911                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6912                         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);
6913                         break;
6914                 case RENDERPATH_D3D9:
6915 #ifdef SUPPORTD3D
6916                         // 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...
6917                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6918                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6919                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6920                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6921                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6922                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6923                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6924                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6925                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6926                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6927                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6928                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6929                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6930                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6931 #endif
6932                         break;
6933                 case RENDERPATH_D3D10:
6934                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6935                         break;
6936                 case RENDERPATH_D3D11:
6937                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6938                         break;
6939                 case RENDERPATH_SOFT:
6940                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6941                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6942                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6943                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6944                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6945                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6946                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6947                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6948                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6949                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6950                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6951                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6952                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6953                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6954                         break;
6955                 default:
6956                         break;
6957                 }
6958                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6959                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6960                 break;
6961         case RENDERPATH_GL11:
6962         case RENDERPATH_GL13:
6963         case RENDERPATH_GLES1:
6964                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6965                 {
6966                         // apply a color tint to the whole view
6967                         R_ResetViewRendering2D(0, NULL, NULL);
6968                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6969                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6970                         R_SetupShader_Generic_NoTexture(false, true);
6971                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6972                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6973                 }
6974                 break;
6975         }
6976 }
6977
6978 matrix4x4_t r_waterscrollmatrix;
6979
6980 void R_UpdateFog(void)
6981 {
6982         // Nehahra fog
6983         if (gamemode == GAME_NEHAHRA)
6984         {
6985                 if (gl_fogenable.integer)
6986                 {
6987                         r_refdef.oldgl_fogenable = true;
6988                         r_refdef.fog_density = gl_fogdensity.value;
6989                         r_refdef.fog_red = gl_fogred.value;
6990                         r_refdef.fog_green = gl_foggreen.value;
6991                         r_refdef.fog_blue = gl_fogblue.value;
6992                         r_refdef.fog_alpha = 1;
6993                         r_refdef.fog_start = 0;
6994                         r_refdef.fog_end = gl_skyclip.value;
6995                         r_refdef.fog_height = 1<<30;
6996                         r_refdef.fog_fadedepth = 128;
6997                 }
6998                 else if (r_refdef.oldgl_fogenable)
6999                 {
7000                         r_refdef.oldgl_fogenable = false;
7001                         r_refdef.fog_density = 0;
7002                         r_refdef.fog_red = 0;
7003                         r_refdef.fog_green = 0;
7004                         r_refdef.fog_blue = 0;
7005                         r_refdef.fog_alpha = 0;
7006                         r_refdef.fog_start = 0;
7007                         r_refdef.fog_end = 0;
7008                         r_refdef.fog_height = 1<<30;
7009                         r_refdef.fog_fadedepth = 128;
7010                 }
7011         }
7012
7013         // fog parms
7014         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7015         r_refdef.fog_start = max(0, r_refdef.fog_start);
7016         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7017
7018         if (r_refdef.fog_density && r_drawfog.integer)
7019         {
7020                 r_refdef.fogenabled = true;
7021                 // this is the point where the fog reaches 0.9986 alpha, which we
7022                 // consider a good enough cutoff point for the texture
7023                 // (0.9986 * 256 == 255.6)
7024                 if (r_fog_exp2.integer)
7025                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7026                 else
7027                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7028                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7029                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7030                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7031                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7032                         R_BuildFogHeightTexture();
7033                 // fog color was already set
7034                 // update the fog texture
7035                 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)
7036                         R_BuildFogTexture();
7037                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7038                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7039         }
7040         else
7041                 r_refdef.fogenabled = false;
7042
7043         // fog color
7044         if (r_refdef.fog_density)
7045         {
7046                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7047                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7048                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7049
7050                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7051                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7052                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7053                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7054
7055                 {
7056                         vec3_t fogvec;
7057                         VectorCopy(r_refdef.fogcolor, fogvec);
7058                         //   color.rgb *= ContrastBoost * SceneBrightness;
7059                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7060                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7061                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7062                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7063                 }
7064         }
7065 }
7066
7067 void R_UpdateVariables(void)
7068 {
7069         R_Textures_Frame();
7070
7071         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7072
7073         r_refdef.farclip = r_farclip_base.value;
7074         if (r_refdef.scene.worldmodel)
7075                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7076         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7077
7078         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7079                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7080         r_refdef.polygonfactor = 0;
7081         r_refdef.polygonoffset = 0;
7082         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7083         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7084
7085         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7086         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7087         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7088         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7089         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7090         if (FAKELIGHT_ENABLED)
7091         {
7092                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7093         }
7094         else if (r_refdef.scene.worldmodel)
7095         {
7096                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7097         }
7098         if (r_showsurfaces.integer)
7099         {
7100                 r_refdef.scene.rtworld = false;
7101                 r_refdef.scene.rtworldshadows = false;
7102                 r_refdef.scene.rtdlight = false;
7103                 r_refdef.scene.rtdlightshadows = false;
7104                 r_refdef.lightmapintensity = 0;
7105         }
7106
7107         r_gpuskeletal = false;
7108         switch(vid.renderpath)
7109         {
7110         case RENDERPATH_GL20:
7111                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7112         case RENDERPATH_D3D9:
7113         case RENDERPATH_D3D10:
7114         case RENDERPATH_D3D11:
7115         case RENDERPATH_SOFT:
7116         case RENDERPATH_GLES2:
7117                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7118                 {
7119                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7120                         {
7121                                 // build GLSL gamma texture
7122 #define RAMPWIDTH 256
7123                                 unsigned short ramp[RAMPWIDTH * 3];
7124                                 unsigned char rampbgr[RAMPWIDTH][4];
7125                                 int i;
7126
7127                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7128
7129                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7130                                 for(i = 0; i < RAMPWIDTH; ++i)
7131                                 {
7132                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7133                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7134                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7135                                         rampbgr[i][3] = 0;
7136                                 }
7137                                 if (r_texture_gammaramps)
7138                                 {
7139                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7140                                 }
7141                                 else
7142                                 {
7143                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7144                                 }
7145                         }
7146                 }
7147                 else
7148                 {
7149                         // remove GLSL gamma texture
7150                 }
7151                 break;
7152         case RENDERPATH_GL11:
7153         case RENDERPATH_GL13:
7154         case RENDERPATH_GLES1:
7155                 break;
7156         }
7157 }
7158
7159 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7160 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7161 /*
7162 ================
7163 R_SelectScene
7164 ================
7165 */
7166 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7167         if( scenetype != r_currentscenetype ) {
7168                 // store the old scenetype
7169                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7170                 r_currentscenetype = scenetype;
7171                 // move in the new scene
7172                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7173         }
7174 }
7175
7176 /*
7177 ================
7178 R_GetScenePointer
7179 ================
7180 */
7181 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7182 {
7183         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7184         if( scenetype == r_currentscenetype ) {
7185                 return &r_refdef.scene;
7186         } else {
7187                 return &r_scenes_store[ scenetype ];
7188         }
7189 }
7190
7191 static int R_SortEntities_Compare(const void *ap, const void *bp)
7192 {
7193         const entity_render_t *a = *(const entity_render_t **)ap;
7194         const entity_render_t *b = *(const entity_render_t **)bp;
7195
7196         // 1. compare model
7197         if(a->model < b->model)
7198                 return -1;
7199         if(a->model > b->model)
7200                 return +1;
7201
7202         // 2. compare skin
7203         // TODO possibly calculate the REAL skinnum here first using
7204         // skinscenes?
7205         if(a->skinnum < b->skinnum)
7206                 return -1;
7207         if(a->skinnum > b->skinnum)
7208                 return +1;
7209
7210         // everything we compared is equal
7211         return 0;
7212 }
7213 static void R_SortEntities(void)
7214 {
7215         // below or equal 2 ents, sorting never gains anything
7216         if(r_refdef.scene.numentities <= 2)
7217                 return;
7218         // sort
7219         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7220 }
7221
7222 /*
7223 ================
7224 R_RenderView
7225 ================
7226 */
7227 int dpsoftrast_test;
7228 extern cvar_t r_shadow_bouncegrid;
7229 void R_RenderView(void)
7230 {
7231         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7232         int fbo;
7233         rtexture_t *depthtexture;
7234         rtexture_t *colortexture;
7235
7236         dpsoftrast_test = r_test.integer;
7237
7238         if (r_timereport_active)
7239                 R_TimeReport("start");
7240         r_textureframe++; // used only by R_GetCurrentTexture
7241         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7242
7243         if(R_CompileShader_CheckStaticParms())
7244                 R_GLSL_Restart_f();
7245
7246         if (!r_drawentities.integer)
7247                 r_refdef.scene.numentities = 0;
7248         else if (r_sortentities.integer)
7249                 R_SortEntities();
7250
7251         R_AnimCache_ClearCache();
7252
7253         /* adjust for stereo display */
7254         if(R_Stereo_Active())
7255         {
7256                 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);
7257                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7258         }
7259
7260         if (r_refdef.view.isoverlay)
7261         {
7262                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7263                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7264                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7265                 R_TimeReport("depthclear");
7266
7267                 r_refdef.view.showdebug = false;
7268
7269                 r_fb.water.enabled = false;
7270                 r_fb.water.numwaterplanes = 0;
7271
7272                 R_RenderScene(0, NULL, NULL);
7273
7274                 r_refdef.view.matrix = originalmatrix;
7275
7276                 CHECKGLERROR
7277                 return;
7278         }
7279
7280         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7281         {
7282                 r_refdef.view.matrix = originalmatrix;
7283                 return;
7284         }
7285
7286         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7287
7288         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7289                 // in sRGB fallback, behave similar to true sRGB: convert this
7290                 // value from linear to sRGB
7291                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7292
7293         R_RenderView_UpdateViewVectors();
7294
7295         R_Shadow_UpdateWorldLightSelection();
7296
7297         R_Bloom_StartFrame();
7298
7299         // apply bloom brightness offset
7300         if(r_fb.bloomtexture[0])
7301                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7302
7303         R_Water_StartFrame();
7304
7305         // now we probably have an fbo to render into
7306         fbo = r_fb.fbo;
7307         depthtexture = r_fb.depthtexture;
7308         colortexture = r_fb.colortexture;
7309
7310         CHECKGLERROR
7311         if (r_timereport_active)
7312                 R_TimeReport("viewsetup");
7313
7314         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7315
7316         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7317         {
7318                 R_ClearScreen(r_refdef.fogenabled);
7319                 if (r_timereport_active)
7320                         R_TimeReport("viewclear");
7321         }
7322         r_refdef.view.clear = true;
7323
7324         r_refdef.view.showdebug = true;
7325
7326         R_View_Update();
7327         if (r_timereport_active)
7328                 R_TimeReport("visibility");
7329
7330         R_AnimCache_CacheVisibleEntities();
7331         if (r_timereport_active)
7332                 R_TimeReport("animcache");
7333
7334         R_Shadow_UpdateBounceGridTexture();
7335         if (r_timereport_active && r_shadow_bouncegrid.integer)
7336                 R_TimeReport("bouncegrid");
7337
7338         r_fb.water.numwaterplanes = 0;
7339         if (r_fb.water.enabled)
7340                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7341
7342         R_RenderScene(fbo, depthtexture, colortexture);
7343         r_fb.water.numwaterplanes = 0;
7344
7345         R_BlendView(fbo, depthtexture, colortexture);
7346         if (r_timereport_active)
7347                 R_TimeReport("blendview");
7348
7349         GL_Scissor(0, 0, vid.width, vid.height);
7350         GL_ScissorTest(false);
7351
7352         r_refdef.view.matrix = originalmatrix;
7353
7354         CHECKGLERROR
7355 }
7356
7357 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7358 {
7359         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7360         {
7361                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7362                 if (r_timereport_active)
7363                         R_TimeReport("waterworld");
7364         }
7365
7366         // don't let sound skip if going slow
7367         if (r_refdef.scene.extraupdate)
7368                 S_ExtraUpdate ();
7369
7370         R_DrawModelsAddWaterPlanes();
7371         if (r_timereport_active)
7372                 R_TimeReport("watermodels");
7373
7374         if (r_fb.water.numwaterplanes)
7375         {
7376                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7377                 if (r_timereport_active)
7378                         R_TimeReport("waterscenes");
7379         }
7380 }
7381
7382 extern cvar_t cl_locs_show;
7383 static void R_DrawLocs(void);
7384 static void R_DrawEntityBBoxes(void);
7385 static void R_DrawModelDecals(void);
7386 extern cvar_t cl_decals_newsystem;
7387 extern qboolean r_shadow_usingdeferredprepass;
7388 extern int r_shadow_shadowmapatlas_modelshadows_size;
7389 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7390 {
7391         qboolean shadowmapping = false;
7392
7393         if (r_timereport_active)
7394                 R_TimeReport("beginscene");
7395
7396         r_refdef.stats[r_stat_renders]++;
7397
7398         R_UpdateFog();
7399
7400         // don't let sound skip if going slow
7401         if (r_refdef.scene.extraupdate)
7402                 S_ExtraUpdate ();
7403
7404         R_MeshQueue_BeginScene();
7405
7406         R_SkyStartFrame();
7407
7408         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);
7409
7410         if (r_timereport_active)
7411                 R_TimeReport("skystartframe");
7412
7413         if (cl.csqc_vidvars.drawworld)
7414         {
7415                 // don't let sound skip if going slow
7416                 if (r_refdef.scene.extraupdate)
7417                         S_ExtraUpdate ();
7418
7419                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7420                 {
7421                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7422                         if (r_timereport_active)
7423                                 R_TimeReport("worldsky");
7424                 }
7425
7426                 if (R_DrawBrushModelsSky() && r_timereport_active)
7427                         R_TimeReport("bmodelsky");
7428
7429                 if (skyrendermasked && skyrenderlater)
7430                 {
7431                         // we have to force off the water clipping plane while rendering sky
7432                         R_SetupView(false, fbo, depthtexture, colortexture);
7433                         R_Sky();
7434                         R_SetupView(true, fbo, depthtexture, colortexture);
7435                         if (r_timereport_active)
7436                                 R_TimeReport("sky");
7437                 }
7438         }
7439
7440         R_Shadow_PrepareModelShadows();
7441         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7442         if (r_timereport_active)
7443                 R_TimeReport("preparelights");
7444
7445         // render all the shadowmaps that will be used for this view
7446         shadowmapping = R_Shadow_ShadowMappingEnabled();
7447         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7448         {
7449                 R_Shadow_DrawShadowMaps();
7450                 if (r_timereport_active)
7451                         R_TimeReport("shadowmaps");
7452         }
7453
7454         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7455         if (r_shadow_usingdeferredprepass)
7456                 R_Shadow_DrawPrepass();
7457
7458         // now we begin the forward pass of the view render
7459         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7460         {
7461                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7462                 if (r_timereport_active)
7463                         R_TimeReport("worlddepth");
7464         }
7465         if (r_depthfirst.integer >= 2)
7466         {
7467                 R_DrawModelsDepth();
7468                 if (r_timereport_active)
7469                         R_TimeReport("modeldepth");
7470         }
7471
7472         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7473         {
7474                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7475                 if (r_timereport_active)
7476                         R_TimeReport("world");
7477         }
7478
7479         // don't let sound skip if going slow
7480         if (r_refdef.scene.extraupdate)
7481                 S_ExtraUpdate ();
7482
7483         R_DrawModels();
7484         if (r_timereport_active)
7485                 R_TimeReport("models");
7486
7487         // don't let sound skip if going slow
7488         if (r_refdef.scene.extraupdate)
7489                 S_ExtraUpdate ();
7490
7491         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7492         {
7493                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7494                 R_Shadow_DrawModelShadows();
7495                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7496                 // don't let sound skip if going slow
7497                 if (r_refdef.scene.extraupdate)
7498                         S_ExtraUpdate ();
7499         }
7500
7501         if (!r_shadow_usingdeferredprepass)
7502         {
7503                 R_Shadow_DrawLights();
7504                 if (r_timereport_active)
7505                         R_TimeReport("rtlights");
7506         }
7507
7508         // don't let sound skip if going slow
7509         if (r_refdef.scene.extraupdate)
7510                 S_ExtraUpdate ();
7511
7512         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7513         {
7514                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7515                 R_Shadow_DrawModelShadows();
7516                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7517                 // don't let sound skip if going slow
7518                 if (r_refdef.scene.extraupdate)
7519                         S_ExtraUpdate ();
7520         }
7521
7522         if (cl.csqc_vidvars.drawworld)
7523         {
7524                 if (cl_decals_newsystem.integer)
7525                 {
7526                         R_DrawModelDecals();
7527                         if (r_timereport_active)
7528                                 R_TimeReport("modeldecals");
7529                 }
7530                 else
7531                 {
7532                         R_DrawDecals();
7533                         if (r_timereport_active)
7534                                 R_TimeReport("decals");
7535                 }
7536
7537                 R_DrawParticles();
7538                 if (r_timereport_active)
7539                         R_TimeReport("particles");
7540
7541                 R_DrawExplosions();
7542                 if (r_timereport_active)
7543                         R_TimeReport("explosions");
7544
7545                 R_DrawLightningBeams();
7546                 if (r_timereport_active)
7547                         R_TimeReport("lightning");
7548         }
7549
7550         if (cl.csqc_loaded)
7551                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7552
7553         if (r_refdef.view.showdebug)
7554         {
7555                 if (cl_locs_show.integer)
7556                 {
7557                         R_DrawLocs();
7558                         if (r_timereport_active)
7559                                 R_TimeReport("showlocs");
7560                 }
7561
7562                 if (r_drawportals.integer)
7563                 {
7564                         R_DrawPortals();
7565                         if (r_timereport_active)
7566                                 R_TimeReport("portals");
7567                 }
7568
7569                 if (r_showbboxes.value > 0)
7570                 {
7571                         R_DrawEntityBBoxes();
7572                         if (r_timereport_active)
7573                                 R_TimeReport("bboxes");
7574                 }
7575         }
7576
7577         if (r_transparent.integer)
7578         {
7579                 R_MeshQueue_RenderTransparent();
7580                 if (r_timereport_active)
7581                         R_TimeReport("drawtrans");
7582         }
7583
7584         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))
7585         {
7586                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7587                 if (r_timereport_active)
7588                         R_TimeReport("worlddebug");
7589                 R_DrawModelsDebug();
7590                 if (r_timereport_active)
7591                         R_TimeReport("modeldebug");
7592         }
7593
7594         if (cl.csqc_vidvars.drawworld)
7595         {
7596                 R_Shadow_DrawCoronas();
7597                 if (r_timereport_active)
7598                         R_TimeReport("coronas");
7599         }
7600
7601 #if 0
7602         {
7603                 GL_DepthTest(false);
7604                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7605                 GL_Color(1, 1, 1, 1);
7606                 qglBegin(GL_POLYGON);
7607                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7608                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7609                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7610                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7611                 qglEnd();
7612                 qglBegin(GL_POLYGON);
7613                 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]);
7614                 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]);
7615                 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]);
7616                 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]);
7617                 qglEnd();
7618                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7619         }
7620 #endif
7621
7622         // don't let sound skip if going slow
7623         if (r_refdef.scene.extraupdate)
7624                 S_ExtraUpdate ();
7625 }
7626
7627 static const unsigned short bboxelements[36] =
7628 {
7629         5, 1, 3, 5, 3, 7,
7630         6, 2, 0, 6, 0, 4,
7631         7, 3, 2, 7, 2, 6,
7632         4, 0, 1, 4, 1, 5,
7633         4, 5, 7, 4, 7, 6,
7634         1, 0, 2, 1, 2, 3,
7635 };
7636
7637 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7638 {
7639         int i;
7640         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7641
7642         RSurf_ActiveWorldEntity();
7643
7644         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7645         GL_DepthMask(false);
7646         GL_DepthRange(0, 1);
7647         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7648 //      R_Mesh_ResetTextureState();
7649
7650         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7651         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7652         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7653         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7654         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7655         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7656         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7657         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7658         R_FillColors(color4f, 8, cr, cg, cb, ca);
7659         if (r_refdef.fogenabled)
7660         {
7661                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7662                 {
7663                         f1 = RSurf_FogVertex(v);
7664                         f2 = 1 - f1;
7665                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7666                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7667                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7668                 }
7669         }
7670         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7671         R_Mesh_ResetTextureState();
7672         R_SetupShader_Generic_NoTexture(false, false);
7673         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7674 }
7675
7676 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7677 {
7678         prvm_prog_t *prog = SVVM_prog;
7679         int i;
7680         float color[4];
7681         prvm_edict_t *edict;
7682
7683         // this function draws bounding boxes of server entities
7684         if (!sv.active)
7685                 return;
7686
7687         GL_CullFace(GL_NONE);
7688         R_SetupShader_Generic_NoTexture(false, false);
7689
7690         for (i = 0;i < numsurfaces;i++)
7691         {
7692                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7693                 switch ((int)PRVM_serveredictfloat(edict, solid))
7694                 {
7695                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7696                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7697                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7698                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7699                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7700                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7701                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7702                 }
7703                 color[3] *= r_showbboxes.value;
7704                 color[3] = bound(0, color[3], 1);
7705                 GL_DepthTest(!r_showdisabledepthtest.integer);
7706                 GL_CullFace(r_refdef.view.cullface_front);
7707                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7708         }
7709 }
7710
7711 static void R_DrawEntityBBoxes(void)
7712 {
7713         int i;
7714         prvm_edict_t *edict;
7715         vec3_t center;
7716         prvm_prog_t *prog = SVVM_prog;
7717
7718         // this function draws bounding boxes of server entities
7719         if (!sv.active)
7720                 return;
7721
7722         for (i = 0;i < prog->num_edicts;i++)
7723         {
7724                 edict = PRVM_EDICT_NUM(i);
7725                 if (edict->priv.server->free)
7726                         continue;
7727                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7728                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7729                         continue;
7730                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7731                         continue;
7732                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7733                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7734         }
7735 }
7736
7737 static const int nomodelelement3i[24] =
7738 {
7739         5, 2, 0,
7740         5, 1, 2,
7741         5, 0, 3,
7742         5, 3, 1,
7743         0, 2, 4,
7744         2, 1, 4,
7745         3, 0, 4,
7746         1, 3, 4
7747 };
7748
7749 static const unsigned short nomodelelement3s[24] =
7750 {
7751         5, 2, 0,
7752         5, 1, 2,
7753         5, 0, 3,
7754         5, 3, 1,
7755         0, 2, 4,
7756         2, 1, 4,
7757         3, 0, 4,
7758         1, 3, 4
7759 };
7760
7761 static const float nomodelvertex3f[6*3] =
7762 {
7763         -16,   0,   0,
7764          16,   0,   0,
7765           0, -16,   0,
7766           0,  16,   0,
7767           0,   0, -16,
7768           0,   0,  16
7769 };
7770
7771 static const float nomodelcolor4f[6*4] =
7772 {
7773         0.0f, 0.0f, 0.5f, 1.0f,
7774         0.0f, 0.0f, 0.5f, 1.0f,
7775         0.0f, 0.5f, 0.0f, 1.0f,
7776         0.0f, 0.5f, 0.0f, 1.0f,
7777         0.5f, 0.0f, 0.0f, 1.0f,
7778         0.5f, 0.0f, 0.0f, 1.0f
7779 };
7780
7781 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7782 {
7783         int i;
7784         float f1, f2, *c;
7785         float color4f[6*4];
7786
7787         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);
7788
7789         // this is only called once per entity so numsurfaces is always 1, and
7790         // surfacelist is always {0}, so this code does not handle batches
7791
7792         if (rsurface.ent_flags & RENDER_ADDITIVE)
7793         {
7794                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7795                 GL_DepthMask(false);
7796         }
7797         else if (rsurface.colormod[3] < 1)
7798         {
7799                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7800                 GL_DepthMask(false);
7801         }
7802         else
7803         {
7804                 GL_BlendFunc(GL_ONE, GL_ZERO);
7805                 GL_DepthMask(true);
7806         }
7807         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7808         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7809         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7810         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7811         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7812         for (i = 0, c = color4f;i < 6;i++, c += 4)
7813         {
7814                 c[0] *= rsurface.colormod[0];
7815                 c[1] *= rsurface.colormod[1];
7816                 c[2] *= rsurface.colormod[2];
7817                 c[3] *= rsurface.colormod[3];
7818         }
7819         if (r_refdef.fogenabled)
7820         {
7821                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7822                 {
7823                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7824                         f2 = 1 - f1;
7825                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7826                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7827                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7828                 }
7829         }
7830 //      R_Mesh_ResetTextureState();
7831         R_SetupShader_Generic_NoTexture(false, false);
7832         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7833         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7834 }
7835
7836 void R_DrawNoModel(entity_render_t *ent)
7837 {
7838         vec3_t org;
7839         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7840         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7841                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7842         else
7843                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7844 }
7845
7846 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7847 {
7848         vec3_t right1, right2, diff, normal;
7849
7850         VectorSubtract (org2, org1, normal);
7851
7852         // calculate 'right' vector for start
7853         VectorSubtract (r_refdef.view.origin, org1, diff);
7854         CrossProduct (normal, diff, right1);
7855         VectorNormalize (right1);
7856
7857         // calculate 'right' vector for end
7858         VectorSubtract (r_refdef.view.origin, org2, diff);
7859         CrossProduct (normal, diff, right2);
7860         VectorNormalize (right2);
7861
7862         vert[ 0] = org1[0] + width * right1[0];
7863         vert[ 1] = org1[1] + width * right1[1];
7864         vert[ 2] = org1[2] + width * right1[2];
7865         vert[ 3] = org1[0] - width * right1[0];
7866         vert[ 4] = org1[1] - width * right1[1];
7867         vert[ 5] = org1[2] - width * right1[2];
7868         vert[ 6] = org2[0] - width * right2[0];
7869         vert[ 7] = org2[1] - width * right2[1];
7870         vert[ 8] = org2[2] - width * right2[2];
7871         vert[ 9] = org2[0] + width * right2[0];
7872         vert[10] = org2[1] + width * right2[1];
7873         vert[11] = org2[2] + width * right2[2];
7874 }
7875
7876 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)
7877 {
7878         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7879         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7880         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7881         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7882         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7883         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7884         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7885         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7886         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7887         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7888         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7889         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7890 }
7891
7892 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7893 {
7894         int i;
7895         float *vertex3f;
7896         float v[3];
7897         VectorSet(v, x, y, z);
7898         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7899                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7900                         break;
7901         if (i == mesh->numvertices)
7902         {
7903                 if (mesh->numvertices < mesh->maxvertices)
7904                 {
7905                         VectorCopy(v, vertex3f);
7906                         mesh->numvertices++;
7907                 }
7908                 return mesh->numvertices;
7909         }
7910         else
7911                 return i;
7912 }
7913
7914 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7915 {
7916         int i;
7917         int *e, element[3];
7918         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7919         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7920         e = mesh->element3i + mesh->numtriangles * 3;
7921         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7922         {
7923                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7924                 if (mesh->numtriangles < mesh->maxtriangles)
7925                 {
7926                         *e++ = element[0];
7927                         *e++ = element[1];
7928                         *e++ = element[2];
7929                         mesh->numtriangles++;
7930                 }
7931                 element[1] = element[2];
7932         }
7933 }
7934
7935 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7936 {
7937         int i;
7938         int *e, element[3];
7939         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7940         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7941         e = mesh->element3i + mesh->numtriangles * 3;
7942         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7943         {
7944                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7945                 if (mesh->numtriangles < mesh->maxtriangles)
7946                 {
7947                         *e++ = element[0];
7948                         *e++ = element[1];
7949                         *e++ = element[2];
7950                         mesh->numtriangles++;
7951                 }
7952                 element[1] = element[2];
7953         }
7954 }
7955
7956 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7957 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7958 {
7959         int planenum, planenum2;
7960         int w;
7961         int tempnumpoints;
7962         mplane_t *plane, *plane2;
7963         double maxdist;
7964         double temppoints[2][256*3];
7965         // figure out how large a bounding box we need to properly compute this brush
7966         maxdist = 0;
7967         for (w = 0;w < numplanes;w++)
7968                 maxdist = max(maxdist, fabs(planes[w].dist));
7969         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7970         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7971         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7972         {
7973                 w = 0;
7974                 tempnumpoints = 4;
7975                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7976                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7977                 {
7978                         if (planenum2 == planenum)
7979                                 continue;
7980                         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);
7981                         w = !w;
7982                 }
7983                 if (tempnumpoints < 3)
7984                         continue;
7985                 // generate elements forming a triangle fan for this polygon
7986                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7987         }
7988 }
7989
7990 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)
7991 {
7992         texturelayer_t *layer;
7993         layer = t->currentlayers + t->currentnumlayers++;
7994         layer->type = type;
7995         layer->depthmask = depthmask;
7996         layer->blendfunc1 = blendfunc1;
7997         layer->blendfunc2 = blendfunc2;
7998         layer->texture = texture;
7999         layer->texmatrix = *matrix;
8000         layer->color[0] = r;
8001         layer->color[1] = g;
8002         layer->color[2] = b;
8003         layer->color[3] = a;
8004 }
8005
8006 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8007 {
8008         if(parms[0] == 0 && parms[1] == 0)
8009                 return false;
8010         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8011                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8012                         return false;
8013         return true;
8014 }
8015
8016 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8017 {
8018         double index, f;
8019         index = parms[2] + rsurface.shadertime * parms[3];
8020         index -= floor(index);
8021         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8022         {
8023         default:
8024         case Q3WAVEFUNC_NONE:
8025         case Q3WAVEFUNC_NOISE:
8026         case Q3WAVEFUNC_COUNT:
8027                 f = 0;
8028                 break;
8029         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8030         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8031         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8032         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8033         case Q3WAVEFUNC_TRIANGLE:
8034                 index *= 4;
8035                 f = index - floor(index);
8036                 if (index < 1)
8037                 {
8038                         // f = f;
8039                 }
8040                 else if (index < 2)
8041                         f = 1 - f;
8042                 else if (index < 3)
8043                         f = -f;
8044                 else
8045                         f = -(1 - f);
8046                 break;
8047         }
8048         f = parms[0] + parms[1] * f;
8049         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8050                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8051         return (float) f;
8052 }
8053
8054 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8055 {
8056         int w, h, idx;
8057         float shadertime;
8058         float f;
8059         float offsetd[2];
8060         float tcmat[12];
8061         matrix4x4_t matrix, temp;
8062         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8063         // it's better to have one huge fixup every 9 hours than gradual
8064         // degradation over time which looks consistently bad after many hours.
8065         //
8066         // tcmod scroll in particular suffers from this degradation which can't be
8067         // effectively worked around even with floor() tricks because we don't
8068         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8069         // a workaround involving floor() would be incorrect anyway...
8070         shadertime = rsurface.shadertime;
8071         if (shadertime >= 32768.0f)
8072                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8073         switch(tcmod->tcmod)
8074         {
8075                 case Q3TCMOD_COUNT:
8076                 case Q3TCMOD_NONE:
8077                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8078                                 matrix = r_waterscrollmatrix;
8079                         else
8080                                 matrix = identitymatrix;
8081                         break;
8082                 case Q3TCMOD_ENTITYTRANSLATE:
8083                         // this is used in Q3 to allow the gamecode to control texcoord
8084                         // scrolling on the entity, which is not supported in darkplaces yet.
8085                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8086                         break;
8087                 case Q3TCMOD_ROTATE:
8088                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8089                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8090                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8091                         break;
8092                 case Q3TCMOD_SCALE:
8093                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8094                         break;
8095                 case Q3TCMOD_SCROLL:
8096                         // this particular tcmod is a "bug for bug" compatible one with regards to
8097                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8098                         // specifically did the wrapping and so we must mimic that...
8099                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8100                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8101                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8102                         break;
8103                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8104                         w = (int) tcmod->parms[0];
8105                         h = (int) tcmod->parms[1];
8106                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8107                         f = f - floor(f);
8108                         idx = (int) floor(f * w * h);
8109                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8110                         break;
8111                 case Q3TCMOD_STRETCH:
8112                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8113                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8114                         break;
8115                 case Q3TCMOD_TRANSFORM:
8116                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8117                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8118                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8119                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8120                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8121                         break;
8122                 case Q3TCMOD_TURBULENT:
8123                         // this is handled in the RSurf_PrepareVertices function
8124                         matrix = identitymatrix;
8125                         break;
8126         }
8127         temp = *texmatrix;
8128         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8129 }
8130
8131 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8132 {
8133         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8134         char name[MAX_QPATH];
8135         skinframe_t *skinframe;
8136         unsigned char pixels[296*194];
8137         strlcpy(cache->name, skinname, sizeof(cache->name));
8138         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8139         if (developer_loading.integer)
8140                 Con_Printf("loading %s\n", name);
8141         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8142         if (!skinframe || !skinframe->base)
8143         {
8144                 unsigned char *f;
8145                 fs_offset_t filesize;
8146                 skinframe = NULL;
8147                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8148                 if (f)
8149                 {
8150                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8151                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8152                         Mem_Free(f);
8153                 }
8154         }
8155         cache->skinframe = skinframe;
8156 }
8157
8158 texture_t *R_GetCurrentTexture(texture_t *t)
8159 {
8160         int i;
8161         const entity_render_t *ent = rsurface.entity;
8162         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8163         q3shaderinfo_layer_tcmod_t *tcmod;
8164
8165         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8166                 return t->currentframe;
8167         t->update_lastrenderframe = r_textureframe;
8168         t->update_lastrenderentity = (void *)ent;
8169
8170         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8171                 t->camera_entity = ent->entitynumber;
8172         else
8173                 t->camera_entity = 0;
8174
8175         // switch to an alternate material if this is a q1bsp animated material
8176         {
8177                 texture_t *texture = t;
8178                 int s = rsurface.ent_skinnum;
8179                 if ((unsigned int)s >= (unsigned int)model->numskins)
8180                         s = 0;
8181                 if (model->skinscenes)
8182                 {
8183                         if (model->skinscenes[s].framecount > 1)
8184                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8185                         else
8186                                 s = model->skinscenes[s].firstframe;
8187                 }
8188                 if (s > 0)
8189                         t = t + s * model->num_surfaces;
8190                 if (t->animated)
8191                 {
8192                         // use an alternate animation if the entity's frame is not 0,
8193                         // and only if the texture has an alternate animation
8194                         if (t->animated == 2) // q2bsp
8195                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8196                         else if (rsurface.ent_alttextures && t->anim_total[1])
8197                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8198                         else
8199                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8200                 }
8201                 texture->currentframe = t;
8202         }
8203
8204         // update currentskinframe to be a qw skin or animation frame
8205         if (rsurface.ent_qwskin >= 0)
8206         {
8207                 i = rsurface.ent_qwskin;
8208                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8209                 {
8210                         r_qwskincache_size = cl.maxclients;
8211                         if (r_qwskincache)
8212                                 Mem_Free(r_qwskincache);
8213                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8214                 }
8215                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8216                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8217                 t->currentskinframe = r_qwskincache[i].skinframe;
8218                 if (t->materialshaderpass && t->currentskinframe == NULL)
8219                         t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8220         }
8221         else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8222                 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8223         if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8224                 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8225
8226         t->currentmaterialflags = t->basematerialflags;
8227         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8228         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8229                 t->currentalpha *= r_wateralpha.value;
8230         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8231                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8232         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8233                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8234         if (!(rsurface.ent_flags & RENDER_LIGHT))
8235                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8236         else if (FAKELIGHT_ENABLED)
8237         {
8238                 // no modellight if using fakelight for the map
8239         }
8240         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8241         {
8242                 // pick a model lighting mode
8243                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8244                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8245                 else
8246                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8247         }
8248         if (rsurface.ent_flags & RENDER_ADDITIVE)
8249                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8250         else if (t->currentalpha < 1)
8251                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8252         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8253         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8254                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8255         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8256                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8257         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8258                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8259         if (t->backgroundshaderpass)
8260                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8261         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8262         {
8263                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8264                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8265         }
8266         else
8267                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8268         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8269         {
8270                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8271                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8272         }
8273         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8274                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8275
8276         // there is no tcmod
8277         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8278         {
8279                 t->currenttexmatrix = r_waterscrollmatrix;
8280                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8281         }
8282         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8283         {
8284                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8285                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8286         }
8287
8288         if (t->materialshaderpass)
8289                 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8290                         R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8291
8292         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8293         if (t->currentskinframe->qpixels)
8294                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8295         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8296         if (!t->basetexture)
8297                 t->basetexture = r_texture_notexture;
8298         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8299         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8300         t->nmaptexture = t->currentskinframe->nmap;
8301         if (!t->nmaptexture)
8302                 t->nmaptexture = r_texture_blanknormalmap;
8303         t->glosstexture = r_texture_black;
8304         t->glowtexture = t->currentskinframe->glow;
8305         t->fogtexture = t->currentskinframe->fog;
8306         t->reflectmasktexture = t->currentskinframe->reflect;
8307         if (t->backgroundshaderpass)
8308         {
8309                 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8310                         R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8311                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8312                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8313                 t->backgroundglosstexture = r_texture_black;
8314                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8315                 if (!t->backgroundnmaptexture)
8316                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8317                 // make sure that if glow is going to be used, both textures are not NULL
8318                 if (!t->backgroundglowtexture && t->glowtexture)
8319                         t->backgroundglowtexture = r_texture_black;
8320                 if (!t->glowtexture && t->backgroundglowtexture)
8321                         t->glowtexture = r_texture_black;
8322         }
8323         else
8324         {
8325                 t->backgroundbasetexture = r_texture_white;
8326                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8327                 t->backgroundglosstexture = r_texture_black;
8328                 t->backgroundglowtexture = NULL;
8329         }
8330         t->specularpower = r_shadow_glossexponent.value;
8331         // TODO: store reference values for these in the texture?
8332         t->specularscale = 0;
8333         if (r_shadow_gloss.integer > 0)
8334         {
8335                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8336                 {
8337                         if (r_shadow_glossintensity.value > 0)
8338                         {
8339                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8340                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8341                                 t->specularscale = r_shadow_glossintensity.value;
8342                         }
8343                 }
8344                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8345                 {
8346                         t->glosstexture = r_texture_white;
8347                         t->backgroundglosstexture = r_texture_white;
8348                         t->specularscale = r_shadow_gloss2intensity.value;
8349                         t->specularpower = r_shadow_gloss2exponent.value;
8350                 }
8351         }
8352         t->specularscale *= t->specularscalemod;
8353         t->specularpower *= t->specularpowermod;
8354         t->rtlightambient = 0;
8355
8356         // lightmaps mode looks bad with dlights using actual texturing, so turn
8357         // off the colormap and glossmap, but leave the normalmap on as it still
8358         // accurately represents the shading involved
8359         if (gl_lightmaps.integer)
8360         {
8361                 t->basetexture = r_texture_grey128;
8362                 t->pantstexture = r_texture_black;
8363                 t->shirttexture = r_texture_black;
8364                 if (gl_lightmaps.integer < 2)
8365                         t->nmaptexture = r_texture_blanknormalmap;
8366                 t->glosstexture = r_texture_black;
8367                 t->glowtexture = NULL;
8368                 t->fogtexture = NULL;
8369                 t->reflectmasktexture = NULL;
8370                 t->backgroundbasetexture = NULL;
8371                 if (gl_lightmaps.integer < 2)
8372                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8373                 t->backgroundglosstexture = r_texture_black;
8374                 t->backgroundglowtexture = NULL;
8375                 t->specularscale = 0;
8376                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8377         }
8378
8379         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8380         VectorClear(t->dlightcolor);
8381         t->currentnumlayers = 0;
8382         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8383         {
8384                 int blendfunc1, blendfunc2;
8385                 qboolean depthmask;
8386                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8387                 {
8388                         blendfunc1 = GL_SRC_ALPHA;
8389                         blendfunc2 = GL_ONE;
8390                 }
8391                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8392                 {
8393                         blendfunc1 = GL_SRC_ALPHA;
8394                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8395                 }
8396                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8397                 {
8398                         blendfunc1 = t->customblendfunc[0];
8399                         blendfunc2 = t->customblendfunc[1];
8400                 }
8401                 else
8402                 {
8403                         blendfunc1 = GL_ONE;
8404                         blendfunc2 = GL_ZERO;
8405                 }
8406                 // don't colormod evilblend textures
8407                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8408                         VectorSet(t->lightmapcolor, 1, 1, 1);
8409                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8410                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8411                 {
8412                         // fullbright is not affected by r_refdef.lightmapintensity
8413                         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]);
8414                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8415                                 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]);
8416                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8417                                 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]);
8418                 }
8419                 else
8420                 {
8421                         vec3_t ambientcolor;
8422                         float colorscale;
8423                         // set the color tint used for lights affecting this surface
8424                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8425                         colorscale = 2;
8426                         // q3bsp has no lightmap updates, so the lightstylevalue that
8427                         // would normally be baked into the lightmap must be
8428                         // applied to the color
8429                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8430                         if (model->type == mod_brushq3)
8431                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8432                         colorscale *= r_refdef.lightmapintensity;
8433                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8434                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8435                         // basic lit geometry
8436                         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]);
8437                         // add pants/shirt if needed
8438                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8439                                 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]);
8440                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8441                                 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]);
8442                         // now add ambient passes if needed
8443                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8444                         {
8445                                 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]);
8446                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8447                                         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]);
8448                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8449                                         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]);
8450                         }
8451                 }
8452                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8453                         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]);
8454                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8455                 {
8456                         // if this is opaque use alpha blend which will darken the earlier
8457                         // passes cheaply.
8458                         //
8459                         // if this is an alpha blended material, all the earlier passes
8460                         // were darkened by fog already, so we only need to add the fog
8461                         // color ontop through the fog mask texture
8462                         //
8463                         // if this is an additive blended material, all the earlier passes
8464                         // were darkened by fog already, and we should not add fog color
8465                         // (because the background was not darkened, there is no fog color
8466                         // that was lost behind it).
8467                         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]);
8468                 }
8469         }
8470
8471         return t;
8472 }
8473
8474 rsurfacestate_t rsurface;
8475
8476 void RSurf_ActiveWorldEntity(void)
8477 {
8478         dp_model_t *model = r_refdef.scene.worldmodel;
8479         //if (rsurface.entity == r_refdef.scene.worldentity)
8480         //      return;
8481         rsurface.entity = r_refdef.scene.worldentity;
8482         rsurface.skeleton = NULL;
8483         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8484         rsurface.ent_skinnum = 0;
8485         rsurface.ent_qwskin = -1;
8486         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8487         rsurface.shadertime = r_refdef.scene.time;
8488         rsurface.matrix = identitymatrix;
8489         rsurface.inversematrix = identitymatrix;
8490         rsurface.matrixscale = 1;
8491         rsurface.inversematrixscale = 1;
8492         R_EntityMatrix(&identitymatrix);
8493         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8494         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8495         rsurface.fograngerecip = r_refdef.fograngerecip;
8496         rsurface.fogheightfade = r_refdef.fogheightfade;
8497         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8498         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8499         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8500         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8501         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8502         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8503         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8504         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8505         rsurface.colormod[3] = 1;
8506         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);
8507         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8508         rsurface.frameblend[0].lerp = 1;
8509         rsurface.ent_alttextures = false;
8510         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8511         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8512         rsurface.entityskeletaltransform3x4 = NULL;
8513         rsurface.entityskeletaltransform3x4buffer = NULL;
8514         rsurface.entityskeletaltransform3x4offset = 0;
8515         rsurface.entityskeletaltransform3x4size = 0;;
8516         rsurface.entityskeletalnumtransforms = 0;
8517         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8518         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8520         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8521         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8522         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8523         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8524         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8525         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8526         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8527         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8528         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8529         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8530         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8531         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8532         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8533         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8534         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8535         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8536         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8537         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8538         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8539         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8540         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8541         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8542         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8543         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8544         rsurface.modelelement3i = model->surfmesh.data_element3i;
8545         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8546         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8547         rsurface.modelelement3s = model->surfmesh.data_element3s;
8548         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8549         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8550         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8551         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8552         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8553         rsurface.modelsurfaces = model->data_surfaces;
8554         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8555         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8556         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8557         rsurface.modelgeneratedvertex = false;
8558         rsurface.batchgeneratedvertex = false;
8559         rsurface.batchfirstvertex = 0;
8560         rsurface.batchnumvertices = 0;
8561         rsurface.batchfirsttriangle = 0;
8562         rsurface.batchnumtriangles = 0;
8563         rsurface.batchvertex3f  = NULL;
8564         rsurface.batchvertex3f_vertexbuffer = NULL;
8565         rsurface.batchvertex3f_bufferoffset = 0;
8566         rsurface.batchsvector3f = NULL;
8567         rsurface.batchsvector3f_vertexbuffer = NULL;
8568         rsurface.batchsvector3f_bufferoffset = 0;
8569         rsurface.batchtvector3f = NULL;
8570         rsurface.batchtvector3f_vertexbuffer = NULL;
8571         rsurface.batchtvector3f_bufferoffset = 0;
8572         rsurface.batchnormal3f  = NULL;
8573         rsurface.batchnormal3f_vertexbuffer = NULL;
8574         rsurface.batchnormal3f_bufferoffset = 0;
8575         rsurface.batchlightmapcolor4f = NULL;
8576         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8577         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8578         rsurface.batchtexcoordtexture2f = NULL;
8579         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8580         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8581         rsurface.batchtexcoordlightmap2f = NULL;
8582         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8583         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8584         rsurface.batchskeletalindex4ub = NULL;
8585         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8586         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8587         rsurface.batchskeletalweight4ub = NULL;
8588         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8589         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8590         rsurface.batchvertexmesh = NULL;
8591         rsurface.batchvertexmesh_vertexbuffer = NULL;
8592         rsurface.batchvertexmesh_bufferoffset = 0;
8593         rsurface.batchelement3i = NULL;
8594         rsurface.batchelement3i_indexbuffer = NULL;
8595         rsurface.batchelement3i_bufferoffset = 0;
8596         rsurface.batchelement3s = NULL;
8597         rsurface.batchelement3s_indexbuffer = NULL;
8598         rsurface.batchelement3s_bufferoffset = 0;
8599         rsurface.passcolor4f = NULL;
8600         rsurface.passcolor4f_vertexbuffer = NULL;
8601         rsurface.passcolor4f_bufferoffset = 0;
8602         rsurface.forcecurrenttextureupdate = false;
8603 }
8604
8605 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8606 {
8607         dp_model_t *model = ent->model;
8608         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8609         //      return;
8610         rsurface.entity = (entity_render_t *)ent;
8611         rsurface.skeleton = ent->skeleton;
8612         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8613         rsurface.ent_skinnum = ent->skinnum;
8614         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;
8615         rsurface.ent_flags = ent->flags;
8616         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8617         rsurface.matrix = ent->matrix;
8618         rsurface.inversematrix = ent->inversematrix;
8619         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8620         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8621         R_EntityMatrix(&rsurface.matrix);
8622         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8623         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8624         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8625         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8626         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8627         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8628         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8629         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8630         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8631         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8632         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8633         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8634         rsurface.colormod[3] = ent->alpha;
8635         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8636         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8637         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8638         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8639         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8640         if (ent->model->brush.submodel && !prepass)
8641         {
8642                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8643                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8644         }
8645         // if the animcache code decided it should use the shader path, skip the deform step
8646         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8647         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8648         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8649         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8650         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8651         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8652         {
8653                 if (ent->animcache_vertex3f)
8654                 {
8655                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8656                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8657                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8658                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8659                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8660                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8661                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8662                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8663                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8664                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8665                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8666                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8667                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8668                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8669                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8670                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8671                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8672                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8673                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8674                 }
8675                 else if (wanttangents)
8676                 {
8677                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8678                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8679                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8680                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8681                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8682                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8683                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8684                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8685                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8686                         rsurface.modelvertexmesh = NULL;
8687                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8688                         rsurface.modelvertexmesh_bufferoffset = 0;
8689                         rsurface.modelvertex3f_vertexbuffer = NULL;
8690                         rsurface.modelvertex3f_bufferoffset = 0;
8691                         rsurface.modelvertex3f_vertexbuffer = 0;
8692                         rsurface.modelvertex3f_bufferoffset = 0;
8693                         rsurface.modelsvector3f_vertexbuffer = 0;
8694                         rsurface.modelsvector3f_bufferoffset = 0;
8695                         rsurface.modeltvector3f_vertexbuffer = 0;
8696                         rsurface.modeltvector3f_bufferoffset = 0;
8697                         rsurface.modelnormal3f_vertexbuffer = 0;
8698                         rsurface.modelnormal3f_bufferoffset = 0;
8699                 }
8700                 else if (wantnormals)
8701                 {
8702                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8703                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8704                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8705                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8706                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8707                         rsurface.modelsvector3f = NULL;
8708                         rsurface.modeltvector3f = NULL;
8709                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8710                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8711                         rsurface.modelvertexmesh = NULL;
8712                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8713                         rsurface.modelvertexmesh_bufferoffset = 0;
8714                         rsurface.modelvertex3f_vertexbuffer = NULL;
8715                         rsurface.modelvertex3f_bufferoffset = 0;
8716                         rsurface.modelvertex3f_vertexbuffer = 0;
8717                         rsurface.modelvertex3f_bufferoffset = 0;
8718                         rsurface.modelsvector3f_vertexbuffer = 0;
8719                         rsurface.modelsvector3f_bufferoffset = 0;
8720                         rsurface.modeltvector3f_vertexbuffer = 0;
8721                         rsurface.modeltvector3f_bufferoffset = 0;
8722                         rsurface.modelnormal3f_vertexbuffer = 0;
8723                         rsurface.modelnormal3f_bufferoffset = 0;
8724                 }
8725                 else
8726                 {
8727                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8728                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8729                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8730                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8731                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8732                         rsurface.modelsvector3f = NULL;
8733                         rsurface.modeltvector3f = NULL;
8734                         rsurface.modelnormal3f = NULL;
8735                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8736                         rsurface.modelvertexmesh = NULL;
8737                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8738                         rsurface.modelvertexmesh_bufferoffset = 0;
8739                         rsurface.modelvertex3f_vertexbuffer = NULL;
8740                         rsurface.modelvertex3f_bufferoffset = 0;
8741                         rsurface.modelvertex3f_vertexbuffer = 0;
8742                         rsurface.modelvertex3f_bufferoffset = 0;
8743                         rsurface.modelsvector3f_vertexbuffer = 0;
8744                         rsurface.modelsvector3f_bufferoffset = 0;
8745                         rsurface.modeltvector3f_vertexbuffer = 0;
8746                         rsurface.modeltvector3f_bufferoffset = 0;
8747                         rsurface.modelnormal3f_vertexbuffer = 0;
8748                         rsurface.modelnormal3f_bufferoffset = 0;
8749                 }
8750                 rsurface.modelgeneratedvertex = true;
8751         }
8752         else
8753         {
8754                 if (rsurface.entityskeletaltransform3x4)
8755                 {
8756                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8757                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8758                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8759                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8760                 }
8761                 else
8762                 {
8763                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8764                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8765                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8766                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8767                 }
8768                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8769                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8770                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8771                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8772                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8773                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8774                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8775                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8776                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8777                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8778                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8779                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8780                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8781                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8782                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8783                 rsurface.modelgeneratedvertex = false;
8784         }
8785         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8786         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8787         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8788         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8789         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8790         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8791         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8792         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8793         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8794         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8795         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8796         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8797         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8798         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8799         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8800         rsurface.modelelement3i = model->surfmesh.data_element3i;
8801         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8802         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8803         rsurface.modelelement3s = model->surfmesh.data_element3s;
8804         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8805         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8806         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8807         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8808         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8809         rsurface.modelsurfaces = model->data_surfaces;
8810         rsurface.batchgeneratedvertex = false;
8811         rsurface.batchfirstvertex = 0;
8812         rsurface.batchnumvertices = 0;
8813         rsurface.batchfirsttriangle = 0;
8814         rsurface.batchnumtriangles = 0;
8815         rsurface.batchvertex3f  = NULL;
8816         rsurface.batchvertex3f_vertexbuffer = NULL;
8817         rsurface.batchvertex3f_bufferoffset = 0;
8818         rsurface.batchsvector3f = NULL;
8819         rsurface.batchsvector3f_vertexbuffer = NULL;
8820         rsurface.batchsvector3f_bufferoffset = 0;
8821         rsurface.batchtvector3f = NULL;
8822         rsurface.batchtvector3f_vertexbuffer = NULL;
8823         rsurface.batchtvector3f_bufferoffset = 0;
8824         rsurface.batchnormal3f  = NULL;
8825         rsurface.batchnormal3f_vertexbuffer = NULL;
8826         rsurface.batchnormal3f_bufferoffset = 0;
8827         rsurface.batchlightmapcolor4f = NULL;
8828         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8829         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8830         rsurface.batchtexcoordtexture2f = NULL;
8831         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8832         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8833         rsurface.batchtexcoordlightmap2f = NULL;
8834         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8835         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8836         rsurface.batchskeletalindex4ub = NULL;
8837         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8838         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8839         rsurface.batchskeletalweight4ub = NULL;
8840         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8841         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8842         rsurface.batchvertexmesh = NULL;
8843         rsurface.batchvertexmesh_vertexbuffer = NULL;
8844         rsurface.batchvertexmesh_bufferoffset = 0;
8845         rsurface.batchelement3i = NULL;
8846         rsurface.batchelement3i_indexbuffer = NULL;
8847         rsurface.batchelement3i_bufferoffset = 0;
8848         rsurface.batchelement3s = NULL;
8849         rsurface.batchelement3s_indexbuffer = NULL;
8850         rsurface.batchelement3s_bufferoffset = 0;
8851         rsurface.passcolor4f = NULL;
8852         rsurface.passcolor4f_vertexbuffer = NULL;
8853         rsurface.passcolor4f_bufferoffset = 0;
8854         rsurface.forcecurrenttextureupdate = false;
8855 }
8856
8857 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)
8858 {
8859         rsurface.entity = r_refdef.scene.worldentity;
8860         rsurface.skeleton = NULL;
8861         rsurface.ent_skinnum = 0;
8862         rsurface.ent_qwskin = -1;
8863         rsurface.ent_flags = entflags;
8864         rsurface.shadertime = r_refdef.scene.time - shadertime;
8865         rsurface.modelnumvertices = numvertices;
8866         rsurface.modelnumtriangles = numtriangles;
8867         rsurface.matrix = *matrix;
8868         rsurface.inversematrix = *inversematrix;
8869         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8870         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8871         R_EntityMatrix(&rsurface.matrix);
8872         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8873         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8874         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8875         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8876         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8877         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8878         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8879         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8880         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8881         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8882         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8883         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8884         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);
8885         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8886         rsurface.frameblend[0].lerp = 1;
8887         rsurface.ent_alttextures = false;
8888         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8889         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8890         rsurface.entityskeletaltransform3x4 = NULL;
8891         rsurface.entityskeletaltransform3x4buffer = NULL;
8892         rsurface.entityskeletaltransform3x4offset = 0;
8893         rsurface.entityskeletaltransform3x4size = 0;
8894         rsurface.entityskeletalnumtransforms = 0;
8895         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8896         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8897         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8898         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8899         if (wanttangents)
8900         {
8901                 rsurface.modelvertex3f = (float *)vertex3f;
8902                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8903                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8904                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8905         }
8906         else if (wantnormals)
8907         {
8908                 rsurface.modelvertex3f = (float *)vertex3f;
8909                 rsurface.modelsvector3f = NULL;
8910                 rsurface.modeltvector3f = NULL;
8911                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8912         }
8913         else
8914         {
8915                 rsurface.modelvertex3f = (float *)vertex3f;
8916                 rsurface.modelsvector3f = NULL;
8917                 rsurface.modeltvector3f = NULL;
8918                 rsurface.modelnormal3f = NULL;
8919         }
8920         rsurface.modelvertexmesh = NULL;
8921         rsurface.modelvertexmesh_vertexbuffer = NULL;
8922         rsurface.modelvertexmesh_bufferoffset = 0;
8923         rsurface.modelvertex3f_vertexbuffer = 0;
8924         rsurface.modelvertex3f_bufferoffset = 0;
8925         rsurface.modelsvector3f_vertexbuffer = 0;
8926         rsurface.modelsvector3f_bufferoffset = 0;
8927         rsurface.modeltvector3f_vertexbuffer = 0;
8928         rsurface.modeltvector3f_bufferoffset = 0;
8929         rsurface.modelnormal3f_vertexbuffer = 0;
8930         rsurface.modelnormal3f_bufferoffset = 0;
8931         rsurface.modelgeneratedvertex = true;
8932         rsurface.modellightmapcolor4f  = (float *)color4f;
8933         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8934         rsurface.modellightmapcolor4f_bufferoffset = 0;
8935         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8936         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8937         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8938         rsurface.modeltexcoordlightmap2f  = NULL;
8939         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8940         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8941         rsurface.modelskeletalindex4ub = NULL;
8942         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8943         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8944         rsurface.modelskeletalweight4ub = NULL;
8945         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8946         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8947         rsurface.modelelement3i = (int *)element3i;
8948         rsurface.modelelement3i_indexbuffer = NULL;
8949         rsurface.modelelement3i_bufferoffset = 0;
8950         rsurface.modelelement3s = (unsigned short *)element3s;
8951         rsurface.modelelement3s_indexbuffer = NULL;
8952         rsurface.modelelement3s_bufferoffset = 0;
8953         rsurface.modellightmapoffsets = NULL;
8954         rsurface.modelsurfaces = NULL;
8955         rsurface.batchgeneratedvertex = false;
8956         rsurface.batchfirstvertex = 0;
8957         rsurface.batchnumvertices = 0;
8958         rsurface.batchfirsttriangle = 0;
8959         rsurface.batchnumtriangles = 0;
8960         rsurface.batchvertex3f  = NULL;
8961         rsurface.batchvertex3f_vertexbuffer = NULL;
8962         rsurface.batchvertex3f_bufferoffset = 0;
8963         rsurface.batchsvector3f = NULL;
8964         rsurface.batchsvector3f_vertexbuffer = NULL;
8965         rsurface.batchsvector3f_bufferoffset = 0;
8966         rsurface.batchtvector3f = NULL;
8967         rsurface.batchtvector3f_vertexbuffer = NULL;
8968         rsurface.batchtvector3f_bufferoffset = 0;
8969         rsurface.batchnormal3f  = NULL;
8970         rsurface.batchnormal3f_vertexbuffer = NULL;
8971         rsurface.batchnormal3f_bufferoffset = 0;
8972         rsurface.batchlightmapcolor4f = NULL;
8973         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8974         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8975         rsurface.batchtexcoordtexture2f = NULL;
8976         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8977         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8978         rsurface.batchtexcoordlightmap2f = NULL;
8979         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8980         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8981         rsurface.batchskeletalindex4ub = NULL;
8982         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8983         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8984         rsurface.batchskeletalweight4ub = NULL;
8985         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8986         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8987         rsurface.batchvertexmesh = NULL;
8988         rsurface.batchvertexmesh_vertexbuffer = NULL;
8989         rsurface.batchvertexmesh_bufferoffset = 0;
8990         rsurface.batchelement3i = NULL;
8991         rsurface.batchelement3i_indexbuffer = NULL;
8992         rsurface.batchelement3i_bufferoffset = 0;
8993         rsurface.batchelement3s = NULL;
8994         rsurface.batchelement3s_indexbuffer = NULL;
8995         rsurface.batchelement3s_bufferoffset = 0;
8996         rsurface.passcolor4f = NULL;
8997         rsurface.passcolor4f_vertexbuffer = NULL;
8998         rsurface.passcolor4f_bufferoffset = 0;
8999         rsurface.forcecurrenttextureupdate = true;
9000
9001         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9002         {
9003                 if ((wantnormals || wanttangents) && !normal3f)
9004                 {
9005                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9006                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9007                 }
9008                 if (wanttangents && !svector3f)
9009                 {
9010                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9011                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9012                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9013                 }
9014         }
9015 }
9016
9017 float RSurf_FogPoint(const float *v)
9018 {
9019         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9020         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9021         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9022         float FogHeightFade = r_refdef.fogheightfade;
9023         float fogfrac;
9024         unsigned int fogmasktableindex;
9025         if (r_refdef.fogplaneviewabove)
9026                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9027         else
9028                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9029         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9030         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9031 }
9032
9033 float RSurf_FogVertex(const float *v)
9034 {
9035         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9036         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9037         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9038         float FogHeightFade = rsurface.fogheightfade;
9039         float fogfrac;
9040         unsigned int fogmasktableindex;
9041         if (r_refdef.fogplaneviewabove)
9042                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9043         else
9044                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9045         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9046         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9047 }
9048
9049 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9050 {
9051         int i;
9052         for (i = 0;i < numelements;i++)
9053                 outelement3i[i] = inelement3i[i] + adjust;
9054 }
9055
9056 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9057 extern cvar_t gl_vbo;
9058 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9059 {
9060         int deformindex;
9061         int firsttriangle;
9062         int numtriangles;
9063         int firstvertex;
9064         int endvertex;
9065         int numvertices;
9066         int surfacefirsttriangle;
9067         int surfacenumtriangles;
9068         int surfacefirstvertex;
9069         int surfaceendvertex;
9070         int surfacenumvertices;
9071         int batchnumsurfaces = texturenumsurfaces;
9072         int batchnumvertices;
9073         int batchnumtriangles;
9074         int needsupdate;
9075         int i, j;
9076         qboolean gaps;
9077         qboolean dynamicvertex;
9078         float amplitude;
9079         float animpos;
9080         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9081         float waveparms[4];
9082         unsigned char *ub;
9083         q3shaderinfo_deform_t *deform;
9084         const msurface_t *surface, *firstsurface;
9085         r_vertexmesh_t *vertexmesh;
9086         if (!texturenumsurfaces)
9087                 return;
9088         // find vertex range of this surface batch
9089         gaps = false;
9090         firstsurface = texturesurfacelist[0];
9091         firsttriangle = firstsurface->num_firsttriangle;
9092         batchnumvertices = 0;
9093         batchnumtriangles = 0;
9094         firstvertex = endvertex = firstsurface->num_firstvertex;
9095         for (i = 0;i < texturenumsurfaces;i++)
9096         {
9097                 surface = texturesurfacelist[i];
9098                 if (surface != firstsurface + i)
9099                         gaps = true;
9100                 surfacefirstvertex = surface->num_firstvertex;
9101                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9102                 surfacenumvertices = surface->num_vertices;
9103                 surfacenumtriangles = surface->num_triangles;
9104                 if (firstvertex > surfacefirstvertex)
9105                         firstvertex = surfacefirstvertex;
9106                 if (endvertex < surfaceendvertex)
9107                         endvertex = surfaceendvertex;
9108                 batchnumvertices += surfacenumvertices;
9109                 batchnumtriangles += surfacenumtriangles;
9110         }
9111
9112         r_refdef.stats[r_stat_batch_batches]++;
9113         if (gaps)
9114                 r_refdef.stats[r_stat_batch_withgaps]++;
9115         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9116         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9117         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9118
9119         // we now know the vertex range used, and if there are any gaps in it
9120         rsurface.batchfirstvertex = firstvertex;
9121         rsurface.batchnumvertices = endvertex - firstvertex;
9122         rsurface.batchfirsttriangle = firsttriangle;
9123         rsurface.batchnumtriangles = batchnumtriangles;
9124
9125         // this variable holds flags for which properties have been updated that
9126         // may require regenerating vertexmesh array...
9127         needsupdate = 0;
9128
9129         // check if any dynamic vertex processing must occur
9130         dynamicvertex = false;
9131
9132         // a cvar to force the dynamic vertex path to be taken, for debugging
9133         if (r_batch_debugdynamicvertexpath.integer)
9134         {
9135                 if (!dynamicvertex)
9136                 {
9137                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9138                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9139                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9140                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9141                 }
9142                 dynamicvertex = true;
9143         }
9144
9145         // if there is a chance of animated vertex colors, it's a dynamic batch
9146         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9147         {
9148                 if (!dynamicvertex)
9149                 {
9150                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9151                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9152                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9153                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9154                 }
9155                 dynamicvertex = true;
9156                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9157         }
9158
9159         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9160         {
9161                 switch (deform->deform)
9162                 {
9163                 default:
9164                 case Q3DEFORM_PROJECTIONSHADOW:
9165                 case Q3DEFORM_TEXT0:
9166                 case Q3DEFORM_TEXT1:
9167                 case Q3DEFORM_TEXT2:
9168                 case Q3DEFORM_TEXT3:
9169                 case Q3DEFORM_TEXT4:
9170                 case Q3DEFORM_TEXT5:
9171                 case Q3DEFORM_TEXT6:
9172                 case Q3DEFORM_TEXT7:
9173                 case Q3DEFORM_NONE:
9174                         break;
9175                 case Q3DEFORM_AUTOSPRITE:
9176                         if (!dynamicvertex)
9177                         {
9178                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9179                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9180                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9181                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9182                         }
9183                         dynamicvertex = true;
9184                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9185                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9186                         break;
9187                 case Q3DEFORM_AUTOSPRITE2:
9188                         if (!dynamicvertex)
9189                         {
9190                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9191                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9192                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9193                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9194                         }
9195                         dynamicvertex = true;
9196                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9197                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9198                         break;
9199                 case Q3DEFORM_NORMAL:
9200                         if (!dynamicvertex)
9201                         {
9202                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9203                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9204                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9205                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9206                         }
9207                         dynamicvertex = true;
9208                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9209                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9210                         break;
9211                 case Q3DEFORM_WAVE:
9212                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9213                                 break; // if wavefunc is a nop, ignore this transform
9214                         if (!dynamicvertex)
9215                         {
9216                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9217                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9218                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9219                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9220                         }
9221                         dynamicvertex = true;
9222                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9223                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9224                         break;
9225                 case Q3DEFORM_BULGE:
9226                         if (!dynamicvertex)
9227                         {
9228                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9229                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9230                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9231                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9232                         }
9233                         dynamicvertex = true;
9234                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9235                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9236                         break;
9237                 case Q3DEFORM_MOVE:
9238                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9239                                 break; // if wavefunc is a nop, ignore this transform
9240                         if (!dynamicvertex)
9241                         {
9242                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9243                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9244                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9245                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9246                         }
9247                         dynamicvertex = true;
9248                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9249                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9250                         break;
9251                 }
9252         }
9253         if (rsurface.texture->materialshaderpass)
9254         {
9255                 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9256                 {
9257                 default:
9258                 case Q3TCGEN_TEXTURE:
9259                         break;
9260                 case Q3TCGEN_LIGHTMAP:
9261                         if (!dynamicvertex)
9262                         {
9263                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9264                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9265                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9266                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9267                         }
9268                         dynamicvertex = true;
9269                         batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9270                         needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9271                         break;
9272                 case Q3TCGEN_VECTOR:
9273                         if (!dynamicvertex)
9274                         {
9275                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9276                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9277                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9278                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9279                         }
9280                         dynamicvertex = true;
9281                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9282                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9283                         break;
9284                 case Q3TCGEN_ENVIRONMENT:
9285                         if (!dynamicvertex)
9286                         {
9287                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9288                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9289                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9290                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9291                         }
9292                         dynamicvertex = true;
9293                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9294                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9295                         break;
9296                 }
9297                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9298                 {
9299                         if (!dynamicvertex)
9300                         {
9301                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9302                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9303                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9304                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9305                         }
9306                         dynamicvertex = true;
9307                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9308                         needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9309                 }
9310         }
9311
9312         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9313         {
9314                 if (!dynamicvertex)
9315                 {
9316                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9317                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9318                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9319                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9320                 }
9321                 dynamicvertex = true;
9322                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9323         }
9324
9325         // when the model data has no vertex buffer (dynamic mesh), we need to
9326         // eliminate gaps
9327         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9328                 batchneed |= BATCHNEED_NOGAPS;
9329
9330         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9331         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9332         // we ensure this by treating the vertex batch as dynamic...
9333         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9334         {
9335                 if (!dynamicvertex)
9336                 {
9337                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9338                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9339                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9340                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9341                 }
9342                 dynamicvertex = true;
9343         }
9344
9345         if (dynamicvertex)
9346         {
9347                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9348                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9349                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9350                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9351                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9352                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9353                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9354                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9355         }
9356
9357         // if needsupdate, we have to do a dynamic vertex batch for sure
9358         if (needsupdate & batchneed)
9359         {
9360                 if (!dynamicvertex)
9361                 {
9362                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9363                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9364                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9365                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9366                 }
9367                 dynamicvertex = true;
9368         }
9369
9370         // see if we need to build vertexmesh from arrays
9371         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9372         {
9373                 if (!dynamicvertex)
9374                 {
9375                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9376                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9377                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9378                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9379                 }
9380                 dynamicvertex = true;
9381         }
9382
9383         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9384         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9385                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9386
9387         rsurface.batchvertex3f = rsurface.modelvertex3f;
9388         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9389         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9390         rsurface.batchsvector3f = rsurface.modelsvector3f;
9391         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9392         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9393         rsurface.batchtvector3f = rsurface.modeltvector3f;
9394         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9395         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9396         rsurface.batchnormal3f = rsurface.modelnormal3f;
9397         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9398         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9399         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9400         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9401         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9402         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9403         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9404         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9405         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9406         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9407         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9408         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9409         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9410         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9411         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9412         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9413         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9414         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9415         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9416         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9417         rsurface.batchelement3i = rsurface.modelelement3i;
9418         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9419         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9420         rsurface.batchelement3s = rsurface.modelelement3s;
9421         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9422         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9423         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9424         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9425         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9426         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9427         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9428
9429         // if any dynamic vertex processing has to occur in software, we copy the
9430         // entire surface list together before processing to rebase the vertices
9431         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9432         //
9433         // if any gaps exist and we do not have a static vertex buffer, we have to
9434         // copy the surface list together to avoid wasting upload bandwidth on the
9435         // vertices in the gaps.
9436         //
9437         // if gaps exist and we have a static vertex buffer, we can choose whether
9438         // to combine the index buffer ranges into one dynamic index buffer or
9439         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9440         //
9441         // in many cases the batch is reduced to one draw call.
9442
9443         rsurface.batchmultidraw = false;
9444         rsurface.batchmultidrawnumsurfaces = 0;
9445         rsurface.batchmultidrawsurfacelist = NULL;
9446
9447         if (!dynamicvertex)
9448         {
9449                 // static vertex data, just set pointers...
9450                 rsurface.batchgeneratedvertex = false;
9451                 // if there are gaps, we want to build a combined index buffer,
9452                 // otherwise use the original static buffer with an appropriate offset
9453                 if (gaps)
9454                 {
9455                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9456                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9457                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9458                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9459                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9460                         {
9461                                 rsurface.batchmultidraw = true;
9462                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9463                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9464                                 return;
9465                         }
9466                         // build a new triangle elements array for this batch
9467                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9468                         rsurface.batchfirsttriangle = 0;
9469                         numtriangles = 0;
9470                         for (i = 0;i < texturenumsurfaces;i++)
9471                         {
9472                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9473                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9474                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9475                                 numtriangles += surfacenumtriangles;
9476                         }
9477                         rsurface.batchelement3i_indexbuffer = NULL;
9478                         rsurface.batchelement3i_bufferoffset = 0;
9479                         rsurface.batchelement3s = NULL;
9480                         rsurface.batchelement3s_indexbuffer = NULL;
9481                         rsurface.batchelement3s_bufferoffset = 0;
9482                         if (endvertex <= 65536)
9483                         {
9484                                 // make a 16bit (unsigned short) index array if possible
9485                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9486                                 for (i = 0;i < numtriangles*3;i++)
9487                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9488                         }
9489                         // upload buffer data for the copytriangles batch
9490                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9491                         {
9492                                 if (rsurface.batchelement3s)
9493                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9494                                 else if (rsurface.batchelement3i)
9495                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9496                         }
9497                 }
9498                 else
9499                 {
9500                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9501                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9502                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9503                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9504                 }
9505                 return;
9506         }
9507
9508         // something needs software processing, do it for real...
9509         // we only directly handle separate array data in this case and then
9510         // generate interleaved data if needed...
9511         rsurface.batchgeneratedvertex = true;
9512         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9513         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9514         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9515         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9516
9517         // now copy the vertex data into a combined array and make an index array
9518         // (this is what Quake3 does all the time)
9519         // we also apply any skeletal animation here that would have been done in
9520         // the vertex shader, because most of the dynamic vertex animation cases
9521         // need actual vertex positions and normals
9522         //if (dynamicvertex)
9523         {
9524                 rsurface.batchvertexmesh = NULL;
9525                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9526                 rsurface.batchvertexmesh_bufferoffset = 0;
9527                 rsurface.batchvertex3f = NULL;
9528                 rsurface.batchvertex3f_vertexbuffer = NULL;
9529                 rsurface.batchvertex3f_bufferoffset = 0;
9530                 rsurface.batchsvector3f = NULL;
9531                 rsurface.batchsvector3f_vertexbuffer = NULL;
9532                 rsurface.batchsvector3f_bufferoffset = 0;
9533                 rsurface.batchtvector3f = NULL;
9534                 rsurface.batchtvector3f_vertexbuffer = NULL;
9535                 rsurface.batchtvector3f_bufferoffset = 0;
9536                 rsurface.batchnormal3f = NULL;
9537                 rsurface.batchnormal3f_vertexbuffer = NULL;
9538                 rsurface.batchnormal3f_bufferoffset = 0;
9539                 rsurface.batchlightmapcolor4f = NULL;
9540                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9541                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9542                 rsurface.batchtexcoordtexture2f = NULL;
9543                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9544                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9545                 rsurface.batchtexcoordlightmap2f = NULL;
9546                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9547                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9548                 rsurface.batchskeletalindex4ub = NULL;
9549                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9550                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9551                 rsurface.batchskeletalweight4ub = NULL;
9552                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9553                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9554                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9555                 rsurface.batchelement3i_indexbuffer = NULL;
9556                 rsurface.batchelement3i_bufferoffset = 0;
9557                 rsurface.batchelement3s = NULL;
9558                 rsurface.batchelement3s_indexbuffer = NULL;
9559                 rsurface.batchelement3s_bufferoffset = 0;
9560                 rsurface.batchskeletaltransform3x4buffer = NULL;
9561                 rsurface.batchskeletaltransform3x4offset = 0;
9562                 rsurface.batchskeletaltransform3x4size = 0;
9563                 // we'll only be setting up certain arrays as needed
9564                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9565                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9566                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9567                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9568                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9569                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9570                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9571                 {
9572                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9573                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9574                 }
9575                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9576                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9577                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9578                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9579                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9580                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9581                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9582                 {
9583                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9584                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9585                 }
9586                 numvertices = 0;
9587                 numtriangles = 0;
9588                 for (i = 0;i < texturenumsurfaces;i++)
9589                 {
9590                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9591                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9592                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9593                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9594                         // copy only the data requested
9595                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9596                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9597                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9598                         {
9599                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9600                                 {
9601                                         if (rsurface.batchvertex3f)
9602                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9603                                         else
9604                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9605                                 }
9606                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9607                                 {
9608                                         if (rsurface.modelnormal3f)
9609                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9610                                         else
9611                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9612                                 }
9613                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9614                                 {
9615                                         if (rsurface.modelsvector3f)
9616                                         {
9617                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9618                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9619                                         }
9620                                         else
9621                                         {
9622                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9623                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9624                                         }
9625                                 }
9626                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9627                                 {
9628                                         if (rsurface.modellightmapcolor4f)
9629                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9630                                         else
9631                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9632                                 }
9633                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9634                                 {
9635                                         if (rsurface.modeltexcoordtexture2f)
9636                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9637                                         else
9638                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9639                                 }
9640                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9641                                 {
9642                                         if (rsurface.modeltexcoordlightmap2f)
9643                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9644                                         else
9645                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9646                                 }
9647                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9648                                 {
9649                                         if (rsurface.modelskeletalindex4ub)
9650                                         {
9651                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9652                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9653                                         }
9654                                         else
9655                                         {
9656                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9657                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9658                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9659                                                 for (j = 0;j < surfacenumvertices;j++)
9660                                                         ub[j*4] = 255;
9661                                         }
9662                                 }
9663                         }
9664                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9665                         numvertices += surfacenumvertices;
9666                         numtriangles += surfacenumtriangles;
9667                 }
9668
9669                 // generate a 16bit index array as well if possible
9670                 // (in general, dynamic batches fit)
9671                 if (numvertices <= 65536)
9672                 {
9673                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9674                         for (i = 0;i < numtriangles*3;i++)
9675                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9676                 }
9677
9678                 // since we've copied everything, the batch now starts at 0
9679                 rsurface.batchfirstvertex = 0;
9680                 rsurface.batchnumvertices = batchnumvertices;
9681                 rsurface.batchfirsttriangle = 0;
9682                 rsurface.batchnumtriangles = batchnumtriangles;
9683         }
9684
9685         // apply skeletal animation that would have been done in the vertex shader
9686         if (rsurface.batchskeletaltransform3x4)
9687         {
9688                 const unsigned char *si;
9689                 const unsigned char *sw;
9690                 const float *t[4];
9691                 const float *b = rsurface.batchskeletaltransform3x4;
9692                 float *vp, *vs, *vt, *vn;
9693                 float w[4];
9694                 float m[3][4], n[3][4];
9695                 float tp[3], ts[3], tt[3], tn[3];
9696                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9697                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9698                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9699                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9700                 si = rsurface.batchskeletalindex4ub;
9701                 sw = rsurface.batchskeletalweight4ub;
9702                 vp = rsurface.batchvertex3f;
9703                 vs = rsurface.batchsvector3f;
9704                 vt = rsurface.batchtvector3f;
9705                 vn = rsurface.batchnormal3f;
9706                 memset(m[0], 0, sizeof(m));
9707                 memset(n[0], 0, sizeof(n));
9708                 for (i = 0;i < batchnumvertices;i++)
9709                 {
9710                         t[0] = b + si[0]*12;
9711                         if (sw[0] == 255)
9712                         {
9713                                 // common case - only one matrix
9714                                 m[0][0] = t[0][ 0];
9715                                 m[0][1] = t[0][ 1];
9716                                 m[0][2] = t[0][ 2];
9717                                 m[0][3] = t[0][ 3];
9718                                 m[1][0] = t[0][ 4];
9719                                 m[1][1] = t[0][ 5];
9720                                 m[1][2] = t[0][ 6];
9721                                 m[1][3] = t[0][ 7];
9722                                 m[2][0] = t[0][ 8];
9723                                 m[2][1] = t[0][ 9];
9724                                 m[2][2] = t[0][10];
9725                                 m[2][3] = t[0][11];
9726                         }
9727                         else if (sw[2] + sw[3])
9728                         {
9729                                 // blend 4 matrices
9730                                 t[1] = b + si[1]*12;
9731                                 t[2] = b + si[2]*12;
9732                                 t[3] = b + si[3]*12;
9733                                 w[0] = sw[0] * (1.0f / 255.0f);
9734                                 w[1] = sw[1] * (1.0f / 255.0f);
9735                                 w[2] = sw[2] * (1.0f / 255.0f);
9736                                 w[3] = sw[3] * (1.0f / 255.0f);
9737                                 // blend the matrices
9738                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9739                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9740                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9741                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9742                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9743                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9744                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9745                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9746                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9747                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9748                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9749                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9750                         }
9751                         else
9752                         {
9753                                 // blend 2 matrices
9754                                 t[1] = b + si[1]*12;
9755                                 w[0] = sw[0] * (1.0f / 255.0f);
9756                                 w[1] = sw[1] * (1.0f / 255.0f);
9757                                 // blend the matrices
9758                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9759                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9760                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9761                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9762                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9763                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9764                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9765                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9766                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9767                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9768                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9769                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9770                         }
9771                         si += 4;
9772                         sw += 4;
9773                         // modify the vertex
9774                         VectorCopy(vp, tp);
9775                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9776                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9777                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9778                         vp += 3;
9779                         if (vn)
9780                         {
9781                                 // the normal transformation matrix is a set of cross products...
9782                                 CrossProduct(m[1], m[2], n[0]);
9783                                 CrossProduct(m[2], m[0], n[1]);
9784                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9785                                 VectorCopy(vn, tn);
9786                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9787                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9788                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9789                                 VectorNormalize(vn);
9790                                 vn += 3;
9791                                 if (vs)
9792                                 {
9793                                         VectorCopy(vs, ts);
9794                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9795                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9796                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9797                                         VectorNormalize(vs);
9798                                         vs += 3;
9799                                         VectorCopy(vt, tt);
9800                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9801                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9802                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9803                                         VectorNormalize(vt);
9804                                         vt += 3;
9805                                 }
9806                         }
9807                 }
9808                 rsurface.batchskeletaltransform3x4 = NULL;
9809                 rsurface.batchskeletalnumtransforms = 0;
9810         }
9811
9812         // q1bsp surfaces rendered in vertex color mode have to have colors
9813         // calculated based on lightstyles
9814         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9815         {
9816                 // generate color arrays for the surfaces in this list
9817                 int c[4];
9818                 int scale;
9819                 int size3;
9820                 const int *offsets;
9821                 const unsigned char *lm;
9822                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9823                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9824                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9825                 numvertices = 0;
9826                 for (i = 0;i < texturenumsurfaces;i++)
9827                 {
9828                         surface = texturesurfacelist[i];
9829                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9830                         surfacenumvertices = surface->num_vertices;
9831                         if (surface->lightmapinfo->samples)
9832                         {
9833                                 for (j = 0;j < surfacenumvertices;j++)
9834                                 {
9835                                         lm = surface->lightmapinfo->samples + offsets[j];
9836                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9837                                         VectorScale(lm, scale, c);
9838                                         if (surface->lightmapinfo->styles[1] != 255)
9839                                         {
9840                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9841                                                 lm += size3;
9842                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9843                                                 VectorMA(c, scale, lm, c);
9844                                                 if (surface->lightmapinfo->styles[2] != 255)
9845                                                 {
9846                                                         lm += size3;
9847                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9848                                                         VectorMA(c, scale, lm, c);
9849                                                         if (surface->lightmapinfo->styles[3] != 255)
9850                                                         {
9851                                                                 lm += size3;
9852                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9853                                                                 VectorMA(c, scale, lm, c);
9854                                                         }
9855                                                 }
9856                                         }
9857                                         c[0] >>= 7;
9858                                         c[1] >>= 7;
9859                                         c[2] >>= 7;
9860                                         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);
9861                                         numvertices++;
9862                                 }
9863                         }
9864                         else
9865                         {
9866                                 for (j = 0;j < surfacenumvertices;j++)
9867                                 {
9868                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9869                                         numvertices++;
9870                                 }
9871                         }
9872                 }
9873         }
9874
9875         // if vertices are deformed (sprite flares and things in maps, possibly
9876         // water waves, bulges and other deformations), modify the copied vertices
9877         // in place
9878         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9879         {
9880                 float scale;
9881                 switch (deform->deform)
9882                 {
9883                 default:
9884                 case Q3DEFORM_PROJECTIONSHADOW:
9885                 case Q3DEFORM_TEXT0:
9886                 case Q3DEFORM_TEXT1:
9887                 case Q3DEFORM_TEXT2:
9888                 case Q3DEFORM_TEXT3:
9889                 case Q3DEFORM_TEXT4:
9890                 case Q3DEFORM_TEXT5:
9891                 case Q3DEFORM_TEXT6:
9892                 case Q3DEFORM_TEXT7:
9893                 case Q3DEFORM_NONE:
9894                         break;
9895                 case Q3DEFORM_AUTOSPRITE:
9896                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9897                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9898                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9899                         VectorNormalize(newforward);
9900                         VectorNormalize(newright);
9901                         VectorNormalize(newup);
9902 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9903 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9904 //                      rsurface.batchvertex3f_bufferoffset = 0;
9905 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9906 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9907 //                      rsurface.batchsvector3f_bufferoffset = 0;
9908 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9909 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9910 //                      rsurface.batchtvector3f_bufferoffset = 0;
9911 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9912 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9913 //                      rsurface.batchnormal3f_bufferoffset = 0;
9914                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9915                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9916                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9917                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9918                                 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);
9919                         // a single autosprite surface can contain multiple sprites...
9920                         for (j = 0;j < batchnumvertices - 3;j += 4)
9921                         {
9922                                 VectorClear(center);
9923                                 for (i = 0;i < 4;i++)
9924                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9925                                 VectorScale(center, 0.25f, center);
9926                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9927                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9928                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9929                                 for (i = 0;i < 4;i++)
9930                                 {
9931                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9932                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9933                                 }
9934                         }
9935                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9936                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9937                         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);
9938                         break;
9939                 case Q3DEFORM_AUTOSPRITE2:
9940                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9941                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9942                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9943                         VectorNormalize(newforward);
9944                         VectorNormalize(newright);
9945                         VectorNormalize(newup);
9946 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9947 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9948 //                      rsurface.batchvertex3f_bufferoffset = 0;
9949                         {
9950                                 const float *v1, *v2;
9951                                 vec3_t start, end;
9952                                 float f, l;
9953                                 struct
9954                                 {
9955                                         float length2;
9956                                         const float *v1;
9957                                         const float *v2;
9958                                 }
9959                                 shortest[2];
9960                                 memset(shortest, 0, sizeof(shortest));
9961                                 // a single autosprite surface can contain multiple sprites...
9962                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9963                                 {
9964                                         VectorClear(center);
9965                                         for (i = 0;i < 4;i++)
9966                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9967                                         VectorScale(center, 0.25f, center);
9968                                         // find the two shortest edges, then use them to define the
9969                                         // axis vectors for rotating around the central axis
9970                                         for (i = 0;i < 6;i++)
9971                                         {
9972                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9973                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9974                                                 l = VectorDistance2(v1, v2);
9975                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9976                                                 if (v1[2] != v2[2])
9977                                                         l += (1.0f / 1024.0f);
9978                                                 if (shortest[0].length2 > l || i == 0)
9979                                                 {
9980                                                         shortest[1] = shortest[0];
9981                                                         shortest[0].length2 = l;
9982                                                         shortest[0].v1 = v1;
9983                                                         shortest[0].v2 = v2;
9984                                                 }
9985                                                 else if (shortest[1].length2 > l || i == 1)
9986                                                 {
9987                                                         shortest[1].length2 = l;
9988                                                         shortest[1].v1 = v1;
9989                                                         shortest[1].v2 = v2;
9990                                                 }
9991                                         }
9992                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9993                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9994                                         // this calculates the right vector from the shortest edge
9995                                         // and the up vector from the edge midpoints
9996                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9997                                         VectorNormalize(right);
9998                                         VectorSubtract(end, start, up);
9999                                         VectorNormalize(up);
10000                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10001                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10002                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10003                                         VectorNegate(forward, forward);
10004                                         VectorReflect(forward, 0, up, forward);
10005                                         VectorNormalize(forward);
10006                                         CrossProduct(up, forward, newright);
10007                                         VectorNormalize(newright);
10008                                         // rotate the quad around the up axis vector, this is made
10009                                         // especially easy by the fact we know the quad is flat,
10010                                         // so we only have to subtract the center position and
10011                                         // measure distance along the right vector, and then
10012                                         // multiply that by the newright vector and add back the
10013                                         // center position
10014                                         // we also need to subtract the old position to undo the
10015                                         // displacement from the center, which we do with a
10016                                         // DotProduct, the subtraction/addition of center is also
10017                                         // optimized into DotProducts here
10018                                         l = DotProduct(right, center);
10019                                         for (i = 0;i < 4;i++)
10020                                         {
10021                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10022                                                 f = DotProduct(right, v1) - l;
10023                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10024                                         }
10025                                 }
10026                         }
10027                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10028                         {
10029 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10031 //                              rsurface.batchnormal3f_bufferoffset = 0;
10032                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10033                         }
10034                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10035                         {
10036 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10037 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10038 //                              rsurface.batchsvector3f_bufferoffset = 0;
10039 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10040 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10041 //                              rsurface.batchtvector3f_bufferoffset = 0;
10042                                 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);
10043                         }
10044                         break;
10045                 case Q3DEFORM_NORMAL:
10046                         // deform the normals to make reflections wavey
10047                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10048                         rsurface.batchnormal3f_vertexbuffer = NULL;
10049                         rsurface.batchnormal3f_bufferoffset = 0;
10050                         for (j = 0;j < batchnumvertices;j++)
10051                         {
10052                                 float vertex[3];
10053                                 float *normal = rsurface.batchnormal3f + 3*j;
10054                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10055                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10056                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10057                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10058                                 VectorNormalize(normal);
10059                         }
10060                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10061                         {
10062 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10063 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10064 //                              rsurface.batchsvector3f_bufferoffset = 0;
10065 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10067 //                              rsurface.batchtvector3f_bufferoffset = 0;
10068                                 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);
10069                         }
10070                         break;
10071                 case Q3DEFORM_WAVE:
10072                         // deform vertex array to make wavey water and flags and such
10073                         waveparms[0] = deform->waveparms[0];
10074                         waveparms[1] = deform->waveparms[1];
10075                         waveparms[2] = deform->waveparms[2];
10076                         waveparms[3] = deform->waveparms[3];
10077                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10078                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10079                         // this is how a divisor of vertex influence on deformation
10080                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10081                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10082 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10083 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10084 //                      rsurface.batchvertex3f_bufferoffset = 0;
10085 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10086 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10087 //                      rsurface.batchnormal3f_bufferoffset = 0;
10088                         for (j = 0;j < batchnumvertices;j++)
10089                         {
10090                                 // if the wavefunc depends on time, evaluate it per-vertex
10091                                 if (waveparms[3])
10092                                 {
10093                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10094                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10095                                 }
10096                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10097                         }
10098                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10099                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10100                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10101                         {
10102 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10103 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10104 //                              rsurface.batchsvector3f_bufferoffset = 0;
10105 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10106 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10107 //                              rsurface.batchtvector3f_bufferoffset = 0;
10108                                 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);
10109                         }
10110                         break;
10111                 case Q3DEFORM_BULGE:
10112                         // deform vertex array to make the surface have moving bulges
10113 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10114 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10115 //                      rsurface.batchvertex3f_bufferoffset = 0;
10116 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10117 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10118 //                      rsurface.batchnormal3f_bufferoffset = 0;
10119                         for (j = 0;j < batchnumvertices;j++)
10120                         {
10121                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10122                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10123                         }
10124                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10125                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10126                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10127                         {
10128 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10129 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10130 //                              rsurface.batchsvector3f_bufferoffset = 0;
10131 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10132 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10133 //                              rsurface.batchtvector3f_bufferoffset = 0;
10134                                 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);
10135                         }
10136                         break;
10137                 case Q3DEFORM_MOVE:
10138                         // deform vertex array
10139                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10140                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10141                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10142                         VectorScale(deform->parms, scale, waveparms);
10143 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10144 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10145 //                      rsurface.batchvertex3f_bufferoffset = 0;
10146                         for (j = 0;j < batchnumvertices;j++)
10147                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10148                         break;
10149                 }
10150         }
10151
10152         if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10153         {
10154         // generate texcoords based on the chosen texcoord source
10155                 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10156                 {
10157                 default:
10158                 case Q3TCGEN_TEXTURE:
10159                         break;
10160                 case Q3TCGEN_LIGHTMAP:
10161         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10162         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10163         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10164                         if (rsurface.batchtexcoordlightmap2f)
10165                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10166                         break;
10167                 case Q3TCGEN_VECTOR:
10168         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10169         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10170         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10171                         for (j = 0;j < batchnumvertices;j++)
10172                         {
10173                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10174                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10175                         }
10176                         break;
10177                 case Q3TCGEN_ENVIRONMENT:
10178                         // make environment reflections using a spheremap
10179                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10180                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10181                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10182                         for (j = 0;j < batchnumvertices;j++)
10183                         {
10184                                 // identical to Q3A's method, but executed in worldspace so
10185                                 // carried models can be shiny too
10186
10187                                 float viewer[3], d, reflected[3], worldreflected[3];
10188
10189                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10190                                 // VectorNormalize(viewer);
10191
10192                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10193
10194                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10195                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10196                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10197                                 // note: this is proportinal to viewer, so we can normalize later
10198
10199                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10200                                 VectorNormalize(worldreflected);
10201
10202                                 // note: this sphere map only uses world x and z!
10203                                 // so positive and negative y will LOOK THE SAME.
10204                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10205                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10206                         }
10207                         break;
10208                 }
10209                 // the only tcmod that needs software vertex processing is turbulent, so
10210                 // check for it here and apply the changes if needed
10211                 // and we only support that as the first one
10212                 // (handling a mixture of turbulent and other tcmods would be problematic
10213                 //  without punting it entirely to a software path)
10214                 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10215                 {
10216                         amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10217                         animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10218         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10219         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10220         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10221                         for (j = 0;j < batchnumvertices;j++)
10222                         {
10223                                 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);
10224                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10225                         }
10226                 }
10227         }
10228
10229         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10230         {
10231                 // convert the modified arrays to vertex structs
10232 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10233 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10234 //              rsurface.batchvertexmesh_bufferoffset = 0;
10235                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10236                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10237                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10238                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10239                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10240                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10241                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10242                 {
10243                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10244                         {
10245                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10246                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10247                         }
10248                 }
10249                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10250                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10251                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10252                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10253                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10254                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10255                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10256                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10257                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10258                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10259                 {
10260                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10261                         {
10262                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10263                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10264                         }
10265                 }
10266         }
10267
10268         // upload buffer data for the dynamic batch
10269         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10270         {
10271                 if (rsurface.batchvertexmesh)
10272                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10273                 else
10274                 {
10275                         if (rsurface.batchvertex3f)
10276                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10277                         if (rsurface.batchsvector3f)
10278                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10279                         if (rsurface.batchtvector3f)
10280                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10281                         if (rsurface.batchnormal3f)
10282                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10283                         if (rsurface.batchlightmapcolor4f)
10284                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10285                         if (rsurface.batchtexcoordtexture2f)
10286                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10287                         if (rsurface.batchtexcoordlightmap2f)
10288                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10289                         if (rsurface.batchskeletalindex4ub)
10290                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10291                         if (rsurface.batchskeletalweight4ub)
10292                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10293                 }
10294                 if (rsurface.batchelement3s)
10295                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10296                 else if (rsurface.batchelement3i)
10297                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10298         }
10299 }
10300
10301 void RSurf_DrawBatch(void)
10302 {
10303         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10304         // through the pipeline, killing it earlier in the pipeline would have
10305         // per-surface overhead rather than per-batch overhead, so it's best to
10306         // reject it here, before it hits glDraw.
10307         if (rsurface.batchnumtriangles == 0)
10308                 return;
10309 #if 0
10310         // batch debugging code
10311         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10312         {
10313                 int i;
10314                 int j;
10315                 int c;
10316                 const int *e;
10317                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10318                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10319                 {
10320                         c = e[i];
10321                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10322                         {
10323                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10324                                 {
10325                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10326                                                 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);
10327                                         break;
10328                                 }
10329                         }
10330                 }
10331         }
10332 #endif
10333         if (rsurface.batchmultidraw)
10334         {
10335                 // issue multiple draws rather than copying index data
10336                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10337                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10338                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10339                 for (i = 0;i < numsurfaces;)
10340                 {
10341                         // combine consecutive surfaces as one draw
10342                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10343                                 if (surfacelist[j] != surfacelist[k] + 1)
10344                                         break;
10345                         firstvertex = surfacelist[i]->num_firstvertex;
10346                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10347                         firsttriangle = surfacelist[i]->num_firsttriangle;
10348                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10349                         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);
10350                         i = j;
10351                 }
10352         }
10353         else
10354         {
10355                 // there is only one consecutive run of index data (may have been combined)
10356                 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);
10357         }
10358 }
10359
10360 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10361 {
10362         // pick the closest matching water plane
10363         int planeindex, vertexindex, bestplaneindex = -1;
10364         float d, bestd;
10365         vec3_t vert;
10366         const float *v;
10367         r_waterstate_waterplane_t *p;
10368         qboolean prepared = false;
10369         bestd = 0;
10370         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10371         {
10372                 if(p->camera_entity != rsurface.texture->camera_entity)
10373                         continue;
10374                 d = 0;
10375                 if(!prepared)
10376                 {
10377                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10378                         prepared = true;
10379                         if(rsurface.batchnumvertices == 0)
10380                                 break;
10381                 }
10382                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10383                 {
10384                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10385                         d += fabs(PlaneDiff(vert, &p->plane));
10386                 }
10387                 if (bestd > d || bestplaneindex < 0)
10388                 {
10389                         bestd = d;
10390                         bestplaneindex = planeindex;
10391                 }
10392         }
10393         return bestplaneindex;
10394         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10395         // this situation though, as it might be better to render single larger
10396         // batches with useless stuff (backface culled for example) than to
10397         // render multiple smaller batches
10398 }
10399
10400 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10401 {
10402         int i;
10403         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10404         rsurface.passcolor4f_vertexbuffer = 0;
10405         rsurface.passcolor4f_bufferoffset = 0;
10406         for (i = 0;i < rsurface.batchnumvertices;i++)
10407                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10408 }
10409
10410 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10411 {
10412         int i;
10413         float f;
10414         const float *v;
10415         const float *c;
10416         float *c2;
10417         if (rsurface.passcolor4f)
10418         {
10419                 // generate color arrays
10420                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10421                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422                 rsurface.passcolor4f_vertexbuffer = 0;
10423                 rsurface.passcolor4f_bufferoffset = 0;
10424                 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)
10425                 {
10426                         f = RSurf_FogVertex(v);
10427                         c2[0] = c[0] * f;
10428                         c2[1] = c[1] * f;
10429                         c2[2] = c[2] * f;
10430                         c2[3] = c[3];
10431                 }
10432         }
10433         else
10434         {
10435                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10436                 rsurface.passcolor4f_vertexbuffer = 0;
10437                 rsurface.passcolor4f_bufferoffset = 0;
10438                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10439                 {
10440                         f = RSurf_FogVertex(v);
10441                         c2[0] = f;
10442                         c2[1] = f;
10443                         c2[2] = f;
10444                         c2[3] = 1;
10445                 }
10446         }
10447 }
10448
10449 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10450 {
10451         int i;
10452         float f;
10453         const float *v;
10454         const float *c;
10455         float *c2;
10456         if (!rsurface.passcolor4f)
10457                 return;
10458         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10459         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10460         rsurface.passcolor4f_vertexbuffer = 0;
10461         rsurface.passcolor4f_bufferoffset = 0;
10462         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)
10463         {
10464                 f = RSurf_FogVertex(v);
10465                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10466                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10467                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10468                 c2[3] = c[3];
10469         }
10470 }
10471
10472 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10473 {
10474         int i;
10475         const float *c;
10476         float *c2;
10477         if (!rsurface.passcolor4f)
10478                 return;
10479         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10480         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10481         rsurface.passcolor4f_vertexbuffer = 0;
10482         rsurface.passcolor4f_bufferoffset = 0;
10483         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10484         {
10485                 c2[0] = c[0] * r;
10486                 c2[1] = c[1] * g;
10487                 c2[2] = c[2] * b;
10488                 c2[3] = c[3] * a;
10489         }
10490 }
10491
10492 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10493 {
10494         int i;
10495         const float *c;
10496         float *c2;
10497         if (!rsurface.passcolor4f)
10498                 return;
10499         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10500         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10501         rsurface.passcolor4f_vertexbuffer = 0;
10502         rsurface.passcolor4f_bufferoffset = 0;
10503         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10504         {
10505                 c2[0] = c[0] + r_refdef.scene.ambient;
10506                 c2[1] = c[1] + r_refdef.scene.ambient;
10507                 c2[2] = c[2] + r_refdef.scene.ambient;
10508                 c2[3] = c[3];
10509         }
10510 }
10511
10512 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10513 {
10514         // TODO: optimize
10515         rsurface.passcolor4f = NULL;
10516         rsurface.passcolor4f_vertexbuffer = 0;
10517         rsurface.passcolor4f_bufferoffset = 0;
10518         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10519         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521         GL_Color(r, g, b, a);
10522         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10523         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10524         R_Mesh_TexMatrix(0, NULL);
10525         RSurf_DrawBatch();
10526 }
10527
10528 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10529 {
10530         // TODO: optimize applyfog && applycolor case
10531         // just apply fog if necessary, and tint the fog color array if necessary
10532         rsurface.passcolor4f = NULL;
10533         rsurface.passcolor4f_vertexbuffer = 0;
10534         rsurface.passcolor4f_bufferoffset = 0;
10535         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10536         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10537         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10538         GL_Color(r, g, b, a);
10539         RSurf_DrawBatch();
10540 }
10541
10542 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10543 {
10544         // TODO: optimize
10545         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10546         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10547         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10548         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10549         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10550         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10551         GL_Color(r, g, b, a);
10552         RSurf_DrawBatch();
10553 }
10554
10555 static void RSurf_DrawBatch_GL11_ClampColor(void)
10556 {
10557         int i;
10558         const float *c1;
10559         float *c2;
10560         if (!rsurface.passcolor4f)
10561                 return;
10562         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10563         {
10564                 c2[0] = bound(0.0f, c1[0], 1.0f);
10565                 c2[1] = bound(0.0f, c1[1], 1.0f);
10566                 c2[2] = bound(0.0f, c1[2], 1.0f);
10567                 c2[3] = bound(0.0f, c1[3], 1.0f);
10568         }
10569 }
10570
10571 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10572 {
10573         int i;
10574         float f;
10575         const float *v;
10576         const float *n;
10577         float *c;
10578         //vec3_t eyedir;
10579
10580         // fake shading
10581         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10582         rsurface.passcolor4f_vertexbuffer = 0;
10583         rsurface.passcolor4f_bufferoffset = 0;
10584         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)
10585         {
10586                 f = -DotProduct(r_refdef.view.forward, n);
10587                 f = max(0, f);
10588                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10589                 f *= r_refdef.lightmapintensity;
10590                 Vector4Set(c, f, f, f, 1);
10591         }
10592 }
10593
10594 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10595 {
10596         RSurf_DrawBatch_GL11_ApplyFakeLight();
10597         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10598         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10599         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10600         GL_Color(r, g, b, a);
10601         RSurf_DrawBatch();
10602 }
10603
10604 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10605 {
10606         int i;
10607         float f;
10608         float alpha;
10609         const float *v;
10610         const float *n;
10611         float *c;
10612         vec3_t ambientcolor;
10613         vec3_t diffusecolor;
10614         vec3_t lightdir;
10615         // TODO: optimize
10616         // model lighting
10617         VectorCopy(rsurface.modellight_lightdir, lightdir);
10618         f = 0.5f * r_refdef.lightmapintensity;
10619         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10620         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10621         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10622         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10623         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10624         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10625         alpha = *a;
10626         if (VectorLength2(diffusecolor) > 0)
10627         {
10628                 // q3-style directional shading
10629                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10630                 rsurface.passcolor4f_vertexbuffer = 0;
10631                 rsurface.passcolor4f_bufferoffset = 0;
10632                 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)
10633                 {
10634                         if ((f = DotProduct(n, lightdir)) > 0)
10635                                 VectorMA(ambientcolor, f, diffusecolor, c);
10636                         else
10637                                 VectorCopy(ambientcolor, c);
10638                         c[3] = alpha;
10639                 }
10640                 *r = 1;
10641                 *g = 1;
10642                 *b = 1;
10643                 *a = 1;
10644                 *applycolor = false;
10645         }
10646         else
10647         {
10648                 *r = ambientcolor[0];
10649                 *g = ambientcolor[1];
10650                 *b = ambientcolor[2];
10651                 rsurface.passcolor4f = NULL;
10652                 rsurface.passcolor4f_vertexbuffer = 0;
10653                 rsurface.passcolor4f_bufferoffset = 0;
10654         }
10655 }
10656
10657 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10658 {
10659         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10660         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10661         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10662         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10663         GL_Color(r, g, b, a);
10664         RSurf_DrawBatch();
10665 }
10666
10667 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10668 {
10669         int i;
10670         float f;
10671         const float *v;
10672         float *c;
10673
10674         // fake shading
10675         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10676         rsurface.passcolor4f_vertexbuffer = 0;
10677         rsurface.passcolor4f_bufferoffset = 0;
10678
10679         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10680         {
10681                 f = 1 - RSurf_FogVertex(v);
10682                 c[0] = r;
10683                 c[1] = g;
10684                 c[2] = b;
10685                 c[3] = f * a;
10686         }
10687 }
10688
10689 void RSurf_SetupDepthAndCulling(void)
10690 {
10691         // submodels are biased to avoid z-fighting with world surfaces that they
10692         // may be exactly overlapping (avoids z-fighting artifacts on certain
10693         // doors and things in Quake maps)
10694         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10695         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10696         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10697         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10698 }
10699
10700 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10701 {
10702         // transparent sky would be ridiculous
10703         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10704                 return;
10705         R_SetupShader_Generic_NoTexture(false, false);
10706         skyrenderlater = true;
10707         RSurf_SetupDepthAndCulling();
10708         GL_DepthMask(true);
10709         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10710         // skymasking on them, and Quake3 never did sky masking (unlike
10711         // software Quake and software Quake2), so disable the sky masking
10712         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10713         // and skymasking also looks very bad when noclipping outside the
10714         // level, so don't use it then either.
10715         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10716         {
10717                 R_Mesh_ResetTextureState();
10718                 if (skyrendermasked)
10719                 {
10720                         R_SetupShader_DepthOrShadow(false, false, false);
10721                         // depth-only (masking)
10722                         GL_ColorMask(0,0,0,0);
10723                         // just to make sure that braindead drivers don't draw
10724                         // anything despite that colormask...
10725                         GL_BlendFunc(GL_ZERO, GL_ONE);
10726                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10727                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10728                 }
10729                 else
10730                 {
10731                         R_SetupShader_Generic_NoTexture(false, false);
10732                         // fog sky
10733                         GL_BlendFunc(GL_ONE, GL_ZERO);
10734                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10735                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10736                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10737                 }
10738                 RSurf_DrawBatch();
10739                 if (skyrendermasked)
10740                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10741         }
10742         R_Mesh_ResetTextureState();
10743         GL_Color(1, 1, 1, 1);
10744 }
10745
10746 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10747 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10748 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10749 {
10750         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10751                 return;
10752         if (prepass)
10753         {
10754                 // render screenspace normalmap to texture
10755                 GL_DepthMask(true);
10756                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10757                 RSurf_DrawBatch();
10758                 return;
10759         }
10760
10761         // bind lightmap texture
10762
10763         // water/refraction/reflection/camera surfaces have to be handled specially
10764         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10765         {
10766                 int start, end, startplaneindex;
10767                 for (start = 0;start < texturenumsurfaces;start = end)
10768                 {
10769                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10770                         if(startplaneindex < 0)
10771                         {
10772                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10773                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10774                                 end = start + 1;
10775                                 continue;
10776                         }
10777                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10778                                 ;
10779                         // now that we have a batch using the same planeindex, render it
10780                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10781                         {
10782                                 // render water or distortion background
10783                                 GL_DepthMask(true);
10784                                 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);
10785                                 RSurf_DrawBatch();
10786                                 // blend surface on top
10787                                 GL_DepthMask(false);
10788                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10789                                 RSurf_DrawBatch();
10790                         }
10791                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10792                         {
10793                                 // render surface with reflection texture as input
10794                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10795                                 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);
10796                                 RSurf_DrawBatch();
10797                         }
10798                 }
10799                 return;
10800         }
10801
10802         // render surface batch normally
10803         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10804         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);
10805         RSurf_DrawBatch();
10806 }
10807
10808 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10809 {
10810         // OpenGL 1.3 path - anything not completely ancient
10811         qboolean applycolor;
10812         qboolean applyfog;
10813         int layerindex;
10814         const texturelayer_t *layer;
10815         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);
10816         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10817
10818         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10819         {
10820                 vec4_t layercolor;
10821                 int layertexrgbscale;
10822                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10823                 {
10824                         if (layerindex == 0)
10825                                 GL_AlphaTest(true);
10826                         else
10827                         {
10828                                 GL_AlphaTest(false);
10829                                 GL_DepthFunc(GL_EQUAL);
10830                         }
10831                 }
10832                 GL_DepthMask(layer->depthmask && writedepth);
10833                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10834                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10835                 {
10836                         layertexrgbscale = 4;
10837                         VectorScale(layer->color, 0.25f, layercolor);
10838                 }
10839                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10840                 {
10841                         layertexrgbscale = 2;
10842                         VectorScale(layer->color, 0.5f, layercolor);
10843                 }
10844                 else
10845                 {
10846                         layertexrgbscale = 1;
10847                         VectorScale(layer->color, 1.0f, layercolor);
10848                 }
10849                 layercolor[3] = layer->color[3];
10850                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10851                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10852                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10853                 switch (layer->type)
10854                 {
10855                 case TEXTURELAYERTYPE_LITTEXTURE:
10856                         // single-pass lightmapped texture with 2x rgbscale
10857                         R_Mesh_TexBind(0, r_texture_white);
10858                         R_Mesh_TexMatrix(0, NULL);
10859                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10860                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10861                         R_Mesh_TexBind(1, layer->texture);
10862                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10863                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10864                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10865                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10866                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10867                         else if (FAKELIGHT_ENABLED)
10868                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10869                         else if (rsurface.uselightmaptexture)
10870                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10871                         else
10872                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10873                         break;
10874                 case TEXTURELAYERTYPE_TEXTURE:
10875                         // singletexture unlit texture with transparency support
10876                         R_Mesh_TexBind(0, layer->texture);
10877                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10878                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10879                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10880                         R_Mesh_TexBind(1, 0);
10881                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10882                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10883                         break;
10884                 case TEXTURELAYERTYPE_FOG:
10885                         // singletexture fogging
10886                         if (layer->texture)
10887                         {
10888                                 R_Mesh_TexBind(0, layer->texture);
10889                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10890                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10891                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10892                         }
10893                         else
10894                         {
10895                                 R_Mesh_TexBind(0, 0);
10896                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10897                         }
10898                         R_Mesh_TexBind(1, 0);
10899                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10900                         // generate a color array for the fog pass
10901                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10902                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10903                         RSurf_DrawBatch();
10904                         break;
10905                 default:
10906                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10907                 }
10908         }
10909         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10910         {
10911                 GL_DepthFunc(GL_LEQUAL);
10912                 GL_AlphaTest(false);
10913         }
10914 }
10915
10916 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10917 {
10918         // OpenGL 1.1 - crusty old voodoo path
10919         qboolean applyfog;
10920         int layerindex;
10921         const texturelayer_t *layer;
10922         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);
10923         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10924
10925         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10926         {
10927                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10928                 {
10929                         if (layerindex == 0)
10930                                 GL_AlphaTest(true);
10931                         else
10932                         {
10933                                 GL_AlphaTest(false);
10934                                 GL_DepthFunc(GL_EQUAL);
10935                         }
10936                 }
10937                 GL_DepthMask(layer->depthmask && writedepth);
10938                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10939                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10940                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10941                 switch (layer->type)
10942                 {
10943                 case TEXTURELAYERTYPE_LITTEXTURE:
10944                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10945                         {
10946                                 // two-pass lit texture with 2x rgbscale
10947                                 // first the lightmap pass
10948                                 R_Mesh_TexBind(0, r_texture_white);
10949                                 R_Mesh_TexMatrix(0, NULL);
10950                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10951                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10952                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10953                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10954                                 else if (FAKELIGHT_ENABLED)
10955                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10956                                 else if (rsurface.uselightmaptexture)
10957                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10958                                 else
10959                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10960                                 // then apply the texture to it
10961                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10962                                 R_Mesh_TexBind(0, layer->texture);
10963                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10964                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10965                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10966                                 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);
10967                         }
10968                         else
10969                         {
10970                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10971                                 R_Mesh_TexBind(0, layer->texture);
10972                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10973                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10974                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10975                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10976                                         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);
10977                                 else if (FAKELIGHT_ENABLED)
10978                                         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);
10979                                 else
10980                                         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);
10981                         }
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, 1, 1);
10988                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10989                         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);
10990                         break;
10991                 case TEXTURELAYERTYPE_FOG:
10992                         // singletexture fogging
10993                         if (layer->texture)
10994                         {
10995                                 R_Mesh_TexBind(0, layer->texture);
10996                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10997                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10998                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10999                         }
11000                         else
11001                         {
11002                                 R_Mesh_TexBind(0, 0);
11003                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11004                         }
11005                         // generate a color array for the fog pass
11006                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11007                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11008                         RSurf_DrawBatch();
11009                         break;
11010                 default:
11011                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11012                 }
11013         }
11014         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11015         {
11016                 GL_DepthFunc(GL_LEQUAL);
11017                 GL_AlphaTest(false);
11018         }
11019 }
11020
11021 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11022 {
11023         int vi;
11024         int j;
11025         r_vertexgeneric_t *batchvertex;
11026         float c[4];
11027
11028 //      R_Mesh_ResetTextureState();
11029         R_SetupShader_Generic_NoTexture(false, false);
11030
11031         if(rsurface.texture && rsurface.texture->currentskinframe)
11032         {
11033                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11034                 c[3] *= rsurface.texture->currentalpha;
11035         }
11036         else
11037         {
11038                 c[0] = 1;
11039                 c[1] = 0;
11040                 c[2] = 1;
11041                 c[3] = 1;
11042         }
11043
11044         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11045         {
11046                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11047                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11048                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11049         }
11050
11051         // brighten it up (as texture value 127 means "unlit")
11052         c[0] *= 2 * r_refdef.view.colorscale;
11053         c[1] *= 2 * r_refdef.view.colorscale;
11054         c[2] *= 2 * r_refdef.view.colorscale;
11055
11056         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11057                 c[3] *= r_wateralpha.value;
11058
11059         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11060         {
11061                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11062                 GL_DepthMask(false);
11063         }
11064         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11065         {
11066                 GL_BlendFunc(GL_ONE, GL_ONE);
11067                 GL_DepthMask(false);
11068         }
11069         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11070         {
11071                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11072                 GL_DepthMask(false);
11073         }
11074         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11075         {
11076                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11077                 GL_DepthMask(false);
11078         }
11079         else
11080         {
11081                 GL_BlendFunc(GL_ONE, GL_ZERO);
11082                 GL_DepthMask(writedepth);
11083         }
11084
11085         if (r_showsurfaces.integer == 3)
11086         {
11087                 rsurface.passcolor4f = NULL;
11088
11089                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11090                 {
11091                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11092
11093                         rsurface.passcolor4f = NULL;
11094                         rsurface.passcolor4f_vertexbuffer = 0;
11095                         rsurface.passcolor4f_bufferoffset = 0;
11096                 }
11097                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11098                 {
11099                         qboolean applycolor = true;
11100                         float one = 1.0;
11101
11102                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11103
11104                         r_refdef.lightmapintensity = 1;
11105                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11106                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11107                 }
11108                 else if (FAKELIGHT_ENABLED)
11109                 {
11110                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11111
11112                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11113                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11114                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11115                 }
11116                 else
11117                 {
11118                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11119
11120                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11121                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11122                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11123                 }
11124
11125                 if(!rsurface.passcolor4f)
11126                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11127
11128                 RSurf_DrawBatch_GL11_ApplyAmbient();
11129                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11130                 if(r_refdef.fogenabled)
11131                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11132                 RSurf_DrawBatch_GL11_ClampColor();
11133
11134                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11135                 R_SetupShader_Generic_NoTexture(false, false);
11136                 RSurf_DrawBatch();
11137         }
11138         else if (!r_refdef.view.showdebug)
11139         {
11140                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11141                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11142                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11143                 {
11144                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11145                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11146                 }
11147                 R_Mesh_PrepareVertices_Generic_Unlock();
11148                 RSurf_DrawBatch();
11149         }
11150         else if (r_showsurfaces.integer == 4)
11151         {
11152                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11153                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11154                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11155                 {
11156                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11157                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11158                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11159                 }
11160                 R_Mesh_PrepareVertices_Generic_Unlock();
11161                 RSurf_DrawBatch();
11162         }
11163         else if (r_showsurfaces.integer == 2)
11164         {
11165                 const int *e;
11166                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11167                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11168                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11169                 {
11170                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11171                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11172                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11173                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11174                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11175                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11176                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11177                 }
11178                 R_Mesh_PrepareVertices_Generic_Unlock();
11179                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11180         }
11181         else
11182         {
11183                 int texturesurfaceindex;
11184                 int k;
11185                 const msurface_t *surface;
11186                 float surfacecolor4f[4];
11187                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11188                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11189                 vi = 0;
11190                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11191                 {
11192                         surface = texturesurfacelist[texturesurfaceindex];
11193                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11194                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11195                         for (j = 0;j < surface->num_vertices;j++)
11196                         {
11197                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11198                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11199                                 vi++;
11200                         }
11201                 }
11202                 R_Mesh_PrepareVertices_Generic_Unlock();
11203                 RSurf_DrawBatch();
11204         }
11205 }
11206
11207 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11208 {
11209         CHECKGLERROR
11210         RSurf_SetupDepthAndCulling();
11211         if (r_showsurfaces.integer)
11212         {
11213                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11214                 return;
11215         }
11216         switch (vid.renderpath)
11217         {
11218         case RENDERPATH_GL20:
11219         case RENDERPATH_D3D9:
11220         case RENDERPATH_D3D10:
11221         case RENDERPATH_D3D11:
11222         case RENDERPATH_SOFT:
11223         case RENDERPATH_GLES2:
11224                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11225                 break;
11226         case RENDERPATH_GL13:
11227         case RENDERPATH_GLES1:
11228                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11229                 break;
11230         case RENDERPATH_GL11:
11231                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11232                 break;
11233         }
11234         CHECKGLERROR
11235 }
11236
11237 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11238 {
11239         CHECKGLERROR
11240         RSurf_SetupDepthAndCulling();
11241         if (r_showsurfaces.integer)
11242         {
11243                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11244                 return;
11245         }
11246         switch (vid.renderpath)
11247         {
11248         case RENDERPATH_GL20:
11249         case RENDERPATH_D3D9:
11250         case RENDERPATH_D3D10:
11251         case RENDERPATH_D3D11:
11252         case RENDERPATH_SOFT:
11253         case RENDERPATH_GLES2:
11254                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11255                 break;
11256         case RENDERPATH_GL13:
11257         case RENDERPATH_GLES1:
11258                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11259                 break;
11260         case RENDERPATH_GL11:
11261                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11262                 break;
11263         }
11264         CHECKGLERROR
11265 }
11266
11267 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11268 {
11269         int i, j;
11270         int texturenumsurfaces, endsurface;
11271         texture_t *texture;
11272         const msurface_t *surface;
11273         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11274
11275         // if the model is static it doesn't matter what value we give for
11276         // wantnormals and wanttangents, so this logic uses only rules applicable
11277         // to a model, knowing that they are meaningless otherwise
11278         if (ent == r_refdef.scene.worldentity)
11279                 RSurf_ActiveWorldEntity();
11280         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11281                 RSurf_ActiveModelEntity(ent, false, false, false);
11282         else
11283         {
11284                 switch (vid.renderpath)
11285                 {
11286                 case RENDERPATH_GL20:
11287                 case RENDERPATH_D3D9:
11288                 case RENDERPATH_D3D10:
11289                 case RENDERPATH_D3D11:
11290                 case RENDERPATH_SOFT:
11291                 case RENDERPATH_GLES2:
11292                         RSurf_ActiveModelEntity(ent, true, true, false);
11293                         break;
11294                 case RENDERPATH_GL11:
11295                 case RENDERPATH_GL13:
11296                 case RENDERPATH_GLES1:
11297                         RSurf_ActiveModelEntity(ent, true, false, false);
11298                         break;
11299                 }
11300         }
11301
11302         if (r_transparentdepthmasking.integer)
11303         {
11304                 qboolean setup = false;
11305                 for (i = 0;i < numsurfaces;i = j)
11306                 {
11307                         j = i + 1;
11308                         surface = rsurface.modelsurfaces + surfacelist[i];
11309                         texture = surface->texture;
11310                         rsurface.texture = R_GetCurrentTexture(texture);
11311                         rsurface.lightmaptexture = NULL;
11312                         rsurface.deluxemaptexture = NULL;
11313                         rsurface.uselightmaptexture = false;
11314                         // scan ahead until we find a different texture
11315                         endsurface = min(i + 1024, numsurfaces);
11316                         texturenumsurfaces = 0;
11317                         texturesurfacelist[texturenumsurfaces++] = surface;
11318                         for (;j < endsurface;j++)
11319                         {
11320                                 surface = rsurface.modelsurfaces + surfacelist[j];
11321                                 if (texture != surface->texture)
11322                                         break;
11323                                 texturesurfacelist[texturenumsurfaces++] = surface;
11324                         }
11325                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11326                                 continue;
11327                         // render the range of surfaces as depth
11328                         if (!setup)
11329                         {
11330                                 setup = true;
11331                                 GL_ColorMask(0,0,0,0);
11332                                 GL_Color(1,1,1,1);
11333                                 GL_DepthTest(true);
11334                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11335                                 GL_DepthMask(true);
11336 //                              R_Mesh_ResetTextureState();
11337                         }
11338                         RSurf_SetupDepthAndCulling();
11339                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11340                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11341                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11342                         RSurf_DrawBatch();
11343                 }
11344                 if (setup)
11345                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11346         }
11347
11348         for (i = 0;i < numsurfaces;i = j)
11349         {
11350                 j = i + 1;
11351                 surface = rsurface.modelsurfaces + surfacelist[i];
11352                 texture = surface->texture;
11353                 rsurface.texture = R_GetCurrentTexture(texture);
11354                 // scan ahead until we find a different texture
11355                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11356                 texturenumsurfaces = 0;
11357                 texturesurfacelist[texturenumsurfaces++] = surface;
11358                 if(FAKELIGHT_ENABLED)
11359                 {
11360                         rsurface.lightmaptexture = NULL;
11361                         rsurface.deluxemaptexture = NULL;
11362                         rsurface.uselightmaptexture = false;
11363                         for (;j < endsurface;j++)
11364                         {
11365                                 surface = rsurface.modelsurfaces + surfacelist[j];
11366                                 if (texture != surface->texture)
11367                                         break;
11368                                 texturesurfacelist[texturenumsurfaces++] = surface;
11369                         }
11370                 }
11371                 else
11372                 {
11373                         rsurface.lightmaptexture = surface->lightmaptexture;
11374                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11375                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11376                         for (;j < endsurface;j++)
11377                         {
11378                                 surface = rsurface.modelsurfaces + surfacelist[j];
11379                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11380                                         break;
11381                                 texturesurfacelist[texturenumsurfaces++] = surface;
11382                         }
11383                 }
11384                 // render the range of surfaces
11385                 if (ent == r_refdef.scene.worldentity)
11386                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11387                 else
11388                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11389         }
11390         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11391 }
11392
11393 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11394 {
11395         // transparent surfaces get pushed off into the transparent queue
11396         int surfacelistindex;
11397         const msurface_t *surface;
11398         vec3_t tempcenter, center;
11399         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11400         {
11401                 surface = texturesurfacelist[surfacelistindex];
11402                 if (r_transparent_sortsurfacesbynearest.integer)
11403                 {
11404                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11405                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11406                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11407                 }
11408                 else
11409                 {
11410                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11411                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11412                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11413                 }
11414                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11415                 if (rsurface.entity->transparent_offset) // transparent offset
11416                 {
11417                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11418                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11419                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11420                 }
11421                 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);
11422         }
11423 }
11424
11425 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11426 {
11427         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11428                 return;
11429         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11430                 return;
11431         RSurf_SetupDepthAndCulling();
11432         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11433         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11434         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11435         RSurf_DrawBatch();
11436 }
11437
11438 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11439 {
11440         CHECKGLERROR
11441         if (depthonly)
11442                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11443         else if (prepass)
11444         {
11445                 if (!rsurface.texture->currentnumlayers)
11446                         return;
11447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11448                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11449                 else
11450                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11451         }
11452         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11453                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11454         else if (!rsurface.texture->currentnumlayers)
11455                 return;
11456         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11457         {
11458                 // in the deferred case, transparent surfaces were queued during prepass
11459                 if (!r_shadow_usingdeferredprepass)
11460                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11461         }
11462         else
11463         {
11464                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11465                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11466         }
11467         CHECKGLERROR
11468 }
11469
11470 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11471 {
11472         int i, j;
11473         texture_t *texture;
11474         R_FrameData_SetMark();
11475         // break the surface list down into batches by texture and use of lightmapping
11476         for (i = 0;i < numsurfaces;i = j)
11477         {
11478                 j = i + 1;
11479                 // texture is the base texture pointer, rsurface.texture is the
11480                 // current frame/skin the texture is directing us to use (for example
11481                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11482                 // use skin 1 instead)
11483                 texture = surfacelist[i]->texture;
11484                 rsurface.texture = R_GetCurrentTexture(texture);
11485                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11486                 {
11487                         // if this texture is not the kind we want, skip ahead to the next one
11488                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11489                                 ;
11490                         continue;
11491                 }
11492                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11493                 {
11494                         rsurface.lightmaptexture = NULL;
11495                         rsurface.deluxemaptexture = NULL;
11496                         rsurface.uselightmaptexture = false;
11497                         // simply scan ahead until we find a different texture or lightmap state
11498                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11499                                 ;
11500                 }
11501                 else
11502                 {
11503                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11504                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11505                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11506                         // simply scan ahead until we find a different texture or lightmap state
11507                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11508                                 ;
11509                 }
11510                 // render the range of surfaces
11511                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11512         }
11513         R_FrameData_ReturnToMark();
11514 }
11515
11516 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11517 {
11518         CHECKGLERROR
11519         if (depthonly)
11520                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11521         else if (prepass)
11522         {
11523                 if (!rsurface.texture->currentnumlayers)
11524                         return;
11525                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11526                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11527                 else
11528                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11529         }
11530         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11531                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11532         else if (!rsurface.texture->currentnumlayers)
11533                 return;
11534         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11535         {
11536                 // in the deferred case, transparent surfaces were queued during prepass
11537                 if (!r_shadow_usingdeferredprepass)
11538                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11539         }
11540         else
11541         {
11542                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11543                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11544         }
11545         CHECKGLERROR
11546 }
11547
11548 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11549 {
11550         int i, j;
11551         texture_t *texture;
11552         R_FrameData_SetMark();
11553         // break the surface list down into batches by texture and use of lightmapping
11554         for (i = 0;i < numsurfaces;i = j)
11555         {
11556                 j = i + 1;
11557                 // texture is the base texture pointer, rsurface.texture is the
11558                 // current frame/skin the texture is directing us to use (for example
11559                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11560                 // use skin 1 instead)
11561                 texture = surfacelist[i]->texture;
11562                 rsurface.texture = R_GetCurrentTexture(texture);
11563                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11564                 {
11565                         // if this texture is not the kind we want, skip ahead to the next one
11566                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11567                                 ;
11568                         continue;
11569                 }
11570                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11571                 {
11572                         rsurface.lightmaptexture = NULL;
11573                         rsurface.deluxemaptexture = NULL;
11574                         rsurface.uselightmaptexture = false;
11575                         // simply scan ahead until we find a different texture or lightmap state
11576                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11577                                 ;
11578                 }
11579                 else
11580                 {
11581                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11582                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11583                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11584                         // simply scan ahead until we find a different texture or lightmap state
11585                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11586                                 ;
11587                 }
11588                 // render the range of surfaces
11589                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11590         }
11591         R_FrameData_ReturnToMark();
11592 }
11593
11594 float locboxvertex3f[6*4*3] =
11595 {
11596         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11597         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11598         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11599         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11600         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11601         1,0,0, 0,0,0, 0,1,0, 1,1,0
11602 };
11603
11604 unsigned short locboxelements[6*2*3] =
11605 {
11606          0, 1, 2, 0, 2, 3,
11607          4, 5, 6, 4, 6, 7,
11608          8, 9,10, 8,10,11,
11609         12,13,14, 12,14,15,
11610         16,17,18, 16,18,19,
11611         20,21,22, 20,22,23
11612 };
11613
11614 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11615 {
11616         int i, j;
11617         cl_locnode_t *loc = (cl_locnode_t *)ent;
11618         vec3_t mins, size;
11619         float vertex3f[6*4*3];
11620         CHECKGLERROR
11621         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11622         GL_DepthMask(false);
11623         GL_DepthRange(0, 1);
11624         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11625         GL_DepthTest(true);
11626         GL_CullFace(GL_NONE);
11627         R_EntityMatrix(&identitymatrix);
11628
11629 //      R_Mesh_ResetTextureState();
11630
11631         i = surfacelist[0];
11632         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11633                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11634                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11635                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11636
11637         if (VectorCompare(loc->mins, loc->maxs))
11638         {
11639                 VectorSet(size, 2, 2, 2);
11640                 VectorMA(loc->mins, -0.5f, size, mins);
11641         }
11642         else
11643         {
11644                 VectorCopy(loc->mins, mins);
11645                 VectorSubtract(loc->maxs, loc->mins, size);
11646         }
11647
11648         for (i = 0;i < 6*4*3;)
11649                 for (j = 0;j < 3;j++, i++)
11650                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11651
11652         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11653         R_SetupShader_Generic_NoTexture(false, false);
11654         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11655 }
11656
11657 void R_DrawLocs(void)
11658 {
11659         int index;
11660         cl_locnode_t *loc, *nearestloc;
11661         vec3_t center;
11662         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11663         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11664         {
11665                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11666                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11667         }
11668 }
11669
11670 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11671 {
11672         if (decalsystem->decals)
11673                 Mem_Free(decalsystem->decals);
11674         memset(decalsystem, 0, sizeof(*decalsystem));
11675 }
11676
11677 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)
11678 {
11679         tridecal_t *decal;
11680         tridecal_t *decals;
11681         int i;
11682
11683         // expand or initialize the system
11684         if (decalsystem->maxdecals <= decalsystem->numdecals)
11685         {
11686                 decalsystem_t old = *decalsystem;
11687                 qboolean useshortelements;
11688                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11689                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11690                 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)));
11691                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11692                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11693                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11694                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11695                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11696                 if (decalsystem->numdecals)
11697                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11698                 if (old.decals)
11699                         Mem_Free(old.decals);
11700                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11701                         decalsystem->element3i[i] = i;
11702                 if (useshortelements)
11703                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11704                                 decalsystem->element3s[i] = i;
11705         }
11706
11707         // grab a decal and search for another free slot for the next one
11708         decals = decalsystem->decals;
11709         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11710         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11711                 ;
11712         decalsystem->freedecal = i;
11713         if (decalsystem->numdecals <= i)
11714                 decalsystem->numdecals = i + 1;
11715
11716         // initialize the decal
11717         decal->lived = 0;
11718         decal->triangleindex = triangleindex;
11719         decal->surfaceindex = surfaceindex;
11720         decal->decalsequence = decalsequence;
11721         decal->color4f[0][0] = c0[0];
11722         decal->color4f[0][1] = c0[1];
11723         decal->color4f[0][2] = c0[2];
11724         decal->color4f[0][3] = 1;
11725         decal->color4f[1][0] = c1[0];
11726         decal->color4f[1][1] = c1[1];
11727         decal->color4f[1][2] = c1[2];
11728         decal->color4f[1][3] = 1;
11729         decal->color4f[2][0] = c2[0];
11730         decal->color4f[2][1] = c2[1];
11731         decal->color4f[2][2] = c2[2];
11732         decal->color4f[2][3] = 1;
11733         decal->vertex3f[0][0] = v0[0];
11734         decal->vertex3f[0][1] = v0[1];
11735         decal->vertex3f[0][2] = v0[2];
11736         decal->vertex3f[1][0] = v1[0];
11737         decal->vertex3f[1][1] = v1[1];
11738         decal->vertex3f[1][2] = v1[2];
11739         decal->vertex3f[2][0] = v2[0];
11740         decal->vertex3f[2][1] = v2[1];
11741         decal->vertex3f[2][2] = v2[2];
11742         decal->texcoord2f[0][0] = t0[0];
11743         decal->texcoord2f[0][1] = t0[1];
11744         decal->texcoord2f[1][0] = t1[0];
11745         decal->texcoord2f[1][1] = t1[1];
11746         decal->texcoord2f[2][0] = t2[0];
11747         decal->texcoord2f[2][1] = t2[1];
11748         TriangleNormal(v0, v1, v2, decal->plane);
11749         VectorNormalize(decal->plane);
11750         decal->plane[3] = DotProduct(v0, decal->plane);
11751 }
11752
11753 extern cvar_t cl_decals_bias;
11754 extern cvar_t cl_decals_models;
11755 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11756 // baseparms, parms, temps
11757 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)
11758 {
11759         int cornerindex;
11760         int index;
11761         float v[9][3];
11762         const float *vertex3f;
11763         const float *normal3f;
11764         int numpoints;
11765         float points[2][9][3];
11766         float temp[3];
11767         float tc[9][2];
11768         float f;
11769         float c[9][4];
11770         const int *e;
11771
11772         e = rsurface.modelelement3i + 3*triangleindex;
11773
11774         vertex3f = rsurface.modelvertex3f;
11775         normal3f = rsurface.modelnormal3f;
11776
11777         if (normal3f)
11778         {
11779                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11780                 {
11781                         index = 3*e[cornerindex];
11782                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11783                 }
11784         }
11785         else
11786         {
11787                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11788                 {
11789                         index = 3*e[cornerindex];
11790                         VectorCopy(vertex3f + index, v[cornerindex]);
11791                 }
11792         }
11793
11794         // cull backfaces
11795         //TriangleNormal(v[0], v[1], v[2], normal);
11796         //if (DotProduct(normal, localnormal) < 0.0f)
11797         //      continue;
11798         // clip by each of the box planes formed from the projection matrix
11799         // if anything survives, we emit the decal
11800         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]);
11801         if (numpoints < 3)
11802                 return;
11803         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]);
11804         if (numpoints < 3)
11805                 return;
11806         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]);
11807         if (numpoints < 3)
11808                 return;
11809         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]);
11810         if (numpoints < 3)
11811                 return;
11812         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]);
11813         if (numpoints < 3)
11814                 return;
11815         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]);
11816         if (numpoints < 3)
11817                 return;
11818         // some part of the triangle survived, so we have to accept it...
11819         if (dynamic)
11820         {
11821                 // dynamic always uses the original triangle
11822                 numpoints = 3;
11823                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11824                 {
11825                         index = 3*e[cornerindex];
11826                         VectorCopy(vertex3f + index, v[cornerindex]);
11827                 }
11828         }
11829         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11830         {
11831                 // convert vertex positions to texcoords
11832                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11833                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11834                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11835                 // calculate distance fade from the projection origin
11836                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11837                 f = bound(0.0f, f, 1.0f);
11838                 c[cornerindex][0] = r * f;
11839                 c[cornerindex][1] = g * f;
11840                 c[cornerindex][2] = b * f;
11841                 c[cornerindex][3] = 1.0f;
11842                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11843         }
11844         if (dynamic)
11845                 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);
11846         else
11847                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11848                         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);
11849 }
11850 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)
11851 {
11852         matrix4x4_t projection;
11853         decalsystem_t *decalsystem;
11854         qboolean dynamic;
11855         dp_model_t *model;
11856         const msurface_t *surface;
11857         const msurface_t *surfaces;
11858         const int *surfacelist;
11859         const texture_t *texture;
11860         int numtriangles;
11861         int numsurfacelist;
11862         int surfacelistindex;
11863         int surfaceindex;
11864         int triangleindex;
11865         float localorigin[3];
11866         float localnormal[3];
11867         float localmins[3];
11868         float localmaxs[3];
11869         float localsize;
11870         //float normal[3];
11871         float planes[6][4];
11872         float angles[3];
11873         bih_t *bih;
11874         int bih_triangles_count;
11875         int bih_triangles[256];
11876         int bih_surfaces[256];
11877
11878         decalsystem = &ent->decalsystem;
11879         model = ent->model;
11880         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11881         {
11882                 R_DecalSystem_Reset(&ent->decalsystem);
11883                 return;
11884         }
11885
11886         if (!model->brush.data_leafs && !cl_decals_models.integer)
11887         {
11888                 if (decalsystem->model)
11889                         R_DecalSystem_Reset(decalsystem);
11890                 return;
11891         }
11892
11893         if (decalsystem->model != model)
11894                 R_DecalSystem_Reset(decalsystem);
11895         decalsystem->model = model;
11896
11897         RSurf_ActiveModelEntity(ent, true, false, false);
11898
11899         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11900         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11901         VectorNormalize(localnormal);
11902         localsize = worldsize*rsurface.inversematrixscale;
11903         localmins[0] = localorigin[0] - localsize;
11904         localmins[1] = localorigin[1] - localsize;
11905         localmins[2] = localorigin[2] - localsize;
11906         localmaxs[0] = localorigin[0] + localsize;
11907         localmaxs[1] = localorigin[1] + localsize;
11908         localmaxs[2] = localorigin[2] + localsize;
11909
11910         //VectorCopy(localnormal, planes[4]);
11911         //VectorVectors(planes[4], planes[2], planes[0]);
11912         AnglesFromVectors(angles, localnormal, NULL, false);
11913         AngleVectors(angles, planes[0], planes[2], planes[4]);
11914         VectorNegate(planes[0], planes[1]);
11915         VectorNegate(planes[2], planes[3]);
11916         VectorNegate(planes[4], planes[5]);
11917         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11918         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11919         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11920         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11921         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11922         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11923
11924 #if 1
11925 // works
11926 {
11927         matrix4x4_t forwardprojection;
11928         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11929         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11930 }
11931 #else
11932 // broken
11933 {
11934         float projectionvector[4][3];
11935         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11936         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11937         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11938         projectionvector[0][0] = planes[0][0] * ilocalsize;
11939         projectionvector[0][1] = planes[1][0] * ilocalsize;
11940         projectionvector[0][2] = planes[2][0] * ilocalsize;
11941         projectionvector[1][0] = planes[0][1] * ilocalsize;
11942         projectionvector[1][1] = planes[1][1] * ilocalsize;
11943         projectionvector[1][2] = planes[2][1] * ilocalsize;
11944         projectionvector[2][0] = planes[0][2] * ilocalsize;
11945         projectionvector[2][1] = planes[1][2] * ilocalsize;
11946         projectionvector[2][2] = planes[2][2] * ilocalsize;
11947         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11948         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11949         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11950         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11951 }
11952 #endif
11953
11954         dynamic = model->surfmesh.isanimated;
11955         numsurfacelist = model->nummodelsurfaces;
11956         surfacelist = model->sortedmodelsurfaces;
11957         surfaces = model->data_surfaces;
11958
11959         bih = NULL;
11960         bih_triangles_count = -1;
11961         if(!dynamic)
11962         {
11963                 if(model->render_bih.numleafs)
11964                         bih = &model->render_bih;
11965                 else if(model->collision_bih.numleafs)
11966                         bih = &model->collision_bih;
11967         }
11968         if(bih)
11969                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11970         if(bih_triangles_count == 0)
11971                 return;
11972         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11973                 return;
11974         if(bih_triangles_count > 0)
11975         {
11976                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11977                 {
11978                         surfaceindex = bih_surfaces[triangleindex];
11979                         surface = surfaces + surfaceindex;
11980                         texture = surface->texture;
11981                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11982                                 continue;
11983                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11984                                 continue;
11985                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11986                 }
11987         }
11988         else
11989         {
11990                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11991                 {
11992                         surfaceindex = surfacelist[surfacelistindex];
11993                         surface = surfaces + surfaceindex;
11994                         // check cull box first because it rejects more than any other check
11995                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11996                                 continue;
11997                         // skip transparent surfaces
11998                         texture = surface->texture;
11999                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12000                                 continue;
12001                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12002                                 continue;
12003                         numtriangles = surface->num_triangles;
12004                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12005                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12006                 }
12007         }
12008 }
12009
12010 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12011 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)
12012 {
12013         int renderentityindex;
12014         float worldmins[3];
12015         float worldmaxs[3];
12016         entity_render_t *ent;
12017
12018         if (!cl_decals_newsystem.integer)
12019                 return;
12020
12021         worldmins[0] = worldorigin[0] - worldsize;
12022         worldmins[1] = worldorigin[1] - worldsize;
12023         worldmins[2] = worldorigin[2] - worldsize;
12024         worldmaxs[0] = worldorigin[0] + worldsize;
12025         worldmaxs[1] = worldorigin[1] + worldsize;
12026         worldmaxs[2] = worldorigin[2] + worldsize;
12027
12028         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12029
12030         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12031         {
12032                 ent = r_refdef.scene.entities[renderentityindex];
12033                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12034                         continue;
12035
12036                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12037         }
12038 }
12039
12040 typedef struct r_decalsystem_splatqueue_s
12041 {
12042         vec3_t worldorigin;
12043         vec3_t worldnormal;
12044         float color[4];
12045         float tcrange[4];
12046         float worldsize;
12047         unsigned int decalsequence;
12048 }
12049 r_decalsystem_splatqueue_t;
12050
12051 int r_decalsystem_numqueued = 0;
12052 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12053
12054 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)
12055 {
12056         r_decalsystem_splatqueue_t *queue;
12057
12058         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12059                 return;
12060
12061         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12062         VectorCopy(worldorigin, queue->worldorigin);
12063         VectorCopy(worldnormal, queue->worldnormal);
12064         Vector4Set(queue->color, r, g, b, a);
12065         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12066         queue->worldsize = worldsize;
12067         queue->decalsequence = cl.decalsequence++;
12068 }
12069
12070 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12071 {
12072         int i;
12073         r_decalsystem_splatqueue_t *queue;
12074
12075         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12076                 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);
12077         r_decalsystem_numqueued = 0;
12078 }
12079
12080 extern cvar_t cl_decals_max;
12081 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12082 {
12083         int i;
12084         decalsystem_t *decalsystem = &ent->decalsystem;
12085         int numdecals;
12086         unsigned int killsequence;
12087         tridecal_t *decal;
12088         float frametime;
12089         float lifetime;
12090
12091         if (!decalsystem->numdecals)
12092                 return;
12093
12094         if (r_showsurfaces.integer)
12095                 return;
12096
12097         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12098         {
12099                 R_DecalSystem_Reset(decalsystem);
12100                 return;
12101         }
12102
12103         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12104         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12105
12106         if (decalsystem->lastupdatetime)
12107                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12108         else
12109                 frametime = 0;
12110         decalsystem->lastupdatetime = r_refdef.scene.time;
12111         numdecals = decalsystem->numdecals;
12112
12113         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12114         {
12115                 if (decal->color4f[0][3])
12116                 {
12117                         decal->lived += frametime;
12118                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12119                         {
12120                                 memset(decal, 0, sizeof(*decal));
12121                                 if (decalsystem->freedecal > i)
12122                                         decalsystem->freedecal = i;
12123                         }
12124                 }
12125         }
12126         decal = decalsystem->decals;
12127         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12128                 numdecals--;
12129
12130         // collapse the array by shuffling the tail decals into the gaps
12131         for (;;)
12132         {
12133                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12134                         decalsystem->freedecal++;
12135                 if (decalsystem->freedecal == numdecals)
12136                         break;
12137                 decal[decalsystem->freedecal] = decal[--numdecals];
12138         }
12139
12140         decalsystem->numdecals = numdecals;
12141
12142         if (numdecals <= 0)
12143         {
12144                 // if there are no decals left, reset decalsystem
12145                 R_DecalSystem_Reset(decalsystem);
12146         }
12147 }
12148
12149 extern skinframe_t *decalskinframe;
12150 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12151 {
12152         int i;
12153         decalsystem_t *decalsystem = &ent->decalsystem;
12154         int numdecals;
12155         tridecal_t *decal;
12156         float faderate;
12157         float alpha;
12158         float *v3f;
12159         float *c4f;
12160         float *t2f;
12161         const int *e;
12162         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12163         int numtris = 0;
12164
12165         numdecals = decalsystem->numdecals;
12166         if (!numdecals)
12167                 return;
12168
12169         if (r_showsurfaces.integer)
12170                 return;
12171
12172         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12173         {
12174                 R_DecalSystem_Reset(decalsystem);
12175                 return;
12176         }
12177
12178         // if the model is static it doesn't matter what value we give for
12179         // wantnormals and wanttangents, so this logic uses only rules applicable
12180         // to a model, knowing that they are meaningless otherwise
12181         if (ent == r_refdef.scene.worldentity)
12182                 RSurf_ActiveWorldEntity();
12183         else
12184                 RSurf_ActiveModelEntity(ent, false, false, false);
12185
12186         decalsystem->lastupdatetime = r_refdef.scene.time;
12187
12188         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12189
12190         // update vertex positions for animated models
12191         v3f = decalsystem->vertex3f;
12192         c4f = decalsystem->color4f;
12193         t2f = decalsystem->texcoord2f;
12194         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12195         {
12196                 if (!decal->color4f[0][3])
12197                         continue;
12198
12199                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12200                         continue;
12201
12202                 // skip backfaces
12203                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12204                         continue;
12205
12206                 // update color values for fading decals
12207                 if (decal->lived >= cl_decals_time.value)
12208                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12209                 else
12210                         alpha = 1.0f;
12211
12212                 c4f[ 0] = decal->color4f[0][0] * alpha;
12213                 c4f[ 1] = decal->color4f[0][1] * alpha;
12214                 c4f[ 2] = decal->color4f[0][2] * alpha;
12215                 c4f[ 3] = 1;
12216                 c4f[ 4] = decal->color4f[1][0] * alpha;
12217                 c4f[ 5] = decal->color4f[1][1] * alpha;
12218                 c4f[ 6] = decal->color4f[1][2] * alpha;
12219                 c4f[ 7] = 1;
12220                 c4f[ 8] = decal->color4f[2][0] * alpha;
12221                 c4f[ 9] = decal->color4f[2][1] * alpha;
12222                 c4f[10] = decal->color4f[2][2] * alpha;
12223                 c4f[11] = 1;
12224
12225                 t2f[0] = decal->texcoord2f[0][0];
12226                 t2f[1] = decal->texcoord2f[0][1];
12227                 t2f[2] = decal->texcoord2f[1][0];
12228                 t2f[3] = decal->texcoord2f[1][1];
12229                 t2f[4] = decal->texcoord2f[2][0];
12230                 t2f[5] = decal->texcoord2f[2][1];
12231
12232                 // update vertex positions for animated models
12233                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12234                 {
12235                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12236                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12237                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12238                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12239                 }
12240                 else
12241                 {
12242                         VectorCopy(decal->vertex3f[0], v3f);
12243                         VectorCopy(decal->vertex3f[1], v3f + 3);
12244                         VectorCopy(decal->vertex3f[2], v3f + 6);
12245                 }
12246
12247                 if (r_refdef.fogenabled)
12248                 {
12249                         alpha = RSurf_FogVertex(v3f);
12250                         VectorScale(c4f, alpha, c4f);
12251                         alpha = RSurf_FogVertex(v3f + 3);
12252                         VectorScale(c4f + 4, alpha, c4f + 4);
12253                         alpha = RSurf_FogVertex(v3f + 6);
12254                         VectorScale(c4f + 8, alpha, c4f + 8);
12255                 }
12256
12257                 v3f += 9;
12258                 c4f += 12;
12259                 t2f += 6;
12260                 numtris++;
12261         }
12262
12263         if (numtris > 0)
12264         {
12265                 r_refdef.stats[r_stat_drawndecals] += numtris;
12266
12267                 // now render the decals all at once
12268                 // (this assumes they all use one particle font texture!)
12269                 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);
12270 //              R_Mesh_ResetTextureState();
12271                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12272                 GL_DepthMask(false);
12273                 GL_DepthRange(0, 1);
12274                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12275                 GL_DepthTest(true);
12276                 GL_CullFace(GL_NONE);
12277                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12278                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12279                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12280         }
12281 }
12282
12283 static void R_DrawModelDecals(void)
12284 {
12285         int i, numdecals;
12286
12287         // fade faster when there are too many decals
12288         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12289         for (i = 0;i < r_refdef.scene.numentities;i++)
12290                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12291
12292         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12293         for (i = 0;i < r_refdef.scene.numentities;i++)
12294                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12295                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12296
12297         R_DecalSystem_ApplySplatEntitiesQueue();
12298
12299         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12300         for (i = 0;i < r_refdef.scene.numentities;i++)
12301                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12302
12303         r_refdef.stats[r_stat_totaldecals] += numdecals;
12304
12305         if (r_showsurfaces.integer)
12306                 return;
12307
12308         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12309
12310         for (i = 0;i < r_refdef.scene.numentities;i++)
12311         {
12312                 if (!r_refdef.viewcache.entityvisible[i])
12313                         continue;
12314                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12315                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12316         }
12317 }
12318
12319 extern cvar_t mod_collision_bih;
12320 static void R_DrawDebugModel(void)
12321 {
12322         entity_render_t *ent = rsurface.entity;
12323         int i, j, flagsmask;
12324         const msurface_t *surface;
12325         dp_model_t *model = ent->model;
12326
12327         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12328                 return;
12329
12330         if (r_showoverdraw.value > 0)
12331         {
12332                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12333                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12334                 R_SetupShader_Generic_NoTexture(false, false);
12335                 GL_DepthTest(false);
12336                 GL_DepthMask(false);
12337                 GL_DepthRange(0, 1);
12338                 GL_BlendFunc(GL_ONE, GL_ONE);
12339                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12340                 {
12341                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12342                                 continue;
12343                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12344                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12345                         {
12346                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12347                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12348                                 if (!rsurface.texture->currentlayers->depthmask)
12349                                         GL_Color(c, 0, 0, 1.0f);
12350                                 else if (ent == r_refdef.scene.worldentity)
12351                                         GL_Color(c, c, c, 1.0f);
12352                                 else
12353                                         GL_Color(0, c, 0, 1.0f);
12354                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12355                                 RSurf_DrawBatch();
12356                         }
12357                 }
12358                 rsurface.texture = NULL;
12359         }
12360
12361         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12362
12363 //      R_Mesh_ResetTextureState();
12364         R_SetupShader_Generic_NoTexture(false, false);
12365         GL_DepthRange(0, 1);
12366         GL_DepthTest(!r_showdisabledepthtest.integer);
12367         GL_DepthMask(false);
12368         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12369
12370         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12371         {
12372                 int triangleindex;
12373                 int bihleafindex;
12374                 qboolean cullbox = false;
12375                 const q3mbrush_t *brush;
12376                 const bih_t *bih = &model->collision_bih;
12377                 const bih_leaf_t *bihleaf;
12378                 float vertex3f[3][3];
12379                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12380                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12381                 {
12382                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12383                                 continue;
12384                         switch (bihleaf->type)
12385                         {
12386                         case BIH_BRUSH:
12387                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12388                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12389                                 {
12390                                         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);
12391                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12392                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12393                                 }
12394                                 break;
12395                         case BIH_COLLISIONTRIANGLE:
12396                                 triangleindex = bihleaf->itemindex;
12397                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12398                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12399                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12400                                 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);
12401                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12402                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12403                                 break;
12404                         case BIH_RENDERTRIANGLE:
12405                                 triangleindex = bihleaf->itemindex;
12406                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12407                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12408                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12409                                 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);
12410                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12411                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12412                                 break;
12413                         }
12414                 }
12415         }
12416
12417         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12418
12419 #ifndef USE_GLES2
12420         if (r_showtris.integer && qglPolygonMode)
12421         {
12422                 if (r_showdisabledepthtest.integer)
12423                 {
12424                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12425                         GL_DepthMask(false);
12426                 }
12427                 else
12428                 {
12429                         GL_BlendFunc(GL_ONE, GL_ZERO);
12430                         GL_DepthMask(true);
12431                 }
12432                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12433                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12434                 {
12435                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12436                                 continue;
12437                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12438                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12439                         {
12440                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12441                                 if (!rsurface.texture->currentlayers->depthmask)
12442                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12443                                 else if (ent == r_refdef.scene.worldentity)
12444                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12445                                 else
12446                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12447                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12448                                 RSurf_DrawBatch();
12449                         }
12450                 }
12451                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12452                 rsurface.texture = NULL;
12453         }
12454
12455         if (r_shownormals.value != 0 && qglBegin)
12456         {
12457                 int l, k;
12458                 vec3_t v;
12459                 if (r_showdisabledepthtest.integer)
12460                 {
12461                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12462                         GL_DepthMask(false);
12463                 }
12464                 else
12465                 {
12466                         GL_BlendFunc(GL_ONE, GL_ZERO);
12467                         GL_DepthMask(true);
12468                 }
12469                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12470                 {
12471                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12472                                 continue;
12473                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12474                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12475                         {
12476                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12477                                 qglBegin(GL_LINES);
12478                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12479                                 {
12480                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12481                                         {
12482                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12483                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12484                                                 qglVertex3f(v[0], v[1], v[2]);
12485                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12486                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12487                                                 qglVertex3f(v[0], v[1], v[2]);
12488                                         }
12489                                 }
12490                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12491                                 {
12492                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12493                                         {
12494                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12495                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12496                                                 qglVertex3f(v[0], v[1], v[2]);
12497                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12498                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12499                                                 qglVertex3f(v[0], v[1], v[2]);
12500                                         }
12501                                 }
12502                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12503                                 {
12504                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12505                                         {
12506                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12507                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12508                                                 qglVertex3f(v[0], v[1], v[2]);
12509                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12510                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12511                                                 qglVertex3f(v[0], v[1], v[2]);
12512                                         }
12513                                 }
12514                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12515                                 {
12516                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12517                                         {
12518                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12519                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12520                                                 qglVertex3f(v[0], v[1], v[2]);
12521                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12522                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12523                                                 qglVertex3f(v[0], v[1], v[2]);
12524                                         }
12525                                 }
12526                                 qglEnd();
12527                                 CHECKGLERROR
12528                         }
12529                 }
12530                 rsurface.texture = NULL;
12531         }
12532 #endif
12533 }
12534
12535 int r_maxsurfacelist = 0;
12536 const msurface_t **r_surfacelist = NULL;
12537 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12538 {
12539         int i, j, endj, flagsmask;
12540         dp_model_t *model = r_refdef.scene.worldmodel;
12541         msurface_t *surfaces;
12542         unsigned char *update;
12543         int numsurfacelist = 0;
12544         if (model == NULL)
12545                 return;
12546
12547         if (r_maxsurfacelist < model->num_surfaces)
12548         {
12549                 r_maxsurfacelist = model->num_surfaces;
12550                 if (r_surfacelist)
12551                         Mem_Free((msurface_t**)r_surfacelist);
12552                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12553         }
12554
12555         RSurf_ActiveWorldEntity();
12556
12557         surfaces = model->data_surfaces;
12558         update = model->brushq1.lightmapupdateflags;
12559
12560         // update light styles on this submodel
12561         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12562         {
12563                 model_brush_lightstyleinfo_t *style;
12564                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12565                 {
12566                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12567                         {
12568                                 int *list = style->surfacelist;
12569                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12570                                 for (j = 0;j < style->numsurfaces;j++)
12571                                         update[list[j]] = true;
12572                         }
12573                 }
12574         }
12575
12576         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12577
12578         if (debug)
12579         {
12580                 R_DrawDebugModel();
12581                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12582                 return;
12583         }
12584
12585         rsurface.lightmaptexture = NULL;
12586         rsurface.deluxemaptexture = NULL;
12587         rsurface.uselightmaptexture = false;
12588         rsurface.texture = NULL;
12589         rsurface.rtlight = NULL;
12590         numsurfacelist = 0;
12591         // add visible surfaces to draw list
12592         for (i = 0;i < model->nummodelsurfaces;i++)
12593         {
12594                 j = model->sortedmodelsurfaces[i];
12595                 if (r_refdef.viewcache.world_surfacevisible[j])
12596                         r_surfacelist[numsurfacelist++] = surfaces + j;
12597         }
12598         // update lightmaps if needed
12599         if (model->brushq1.firstrender)
12600         {
12601                 model->brushq1.firstrender = false;
12602                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12603                         if (update[j])
12604                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12605         }
12606         else if (update)
12607         {
12608                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12609                         if (r_refdef.viewcache.world_surfacevisible[j])
12610                                 if (update[j])
12611                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12612         }
12613         // don't do anything if there were no surfaces
12614         if (!numsurfacelist)
12615         {
12616                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12617                 return;
12618         }
12619         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12620
12621         // add to stats if desired
12622         if (r_speeds.integer && !skysurfaces && !depthonly)
12623         {
12624                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12625                 for (j = 0;j < numsurfacelist;j++)
12626                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12627         }
12628
12629         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12630 }
12631
12632 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12633 {
12634         int i, j, endj, flagsmask;
12635         dp_model_t *model = ent->model;
12636         msurface_t *surfaces;
12637         unsigned char *update;
12638         int numsurfacelist = 0;
12639         if (model == NULL)
12640                 return;
12641
12642         if (r_maxsurfacelist < model->num_surfaces)
12643         {
12644                 r_maxsurfacelist = model->num_surfaces;
12645                 if (r_surfacelist)
12646                         Mem_Free((msurface_t **)r_surfacelist);
12647                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12648         }
12649
12650         // if the model is static it doesn't matter what value we give for
12651         // wantnormals and wanttangents, so this logic uses only rules applicable
12652         // to a model, knowing that they are meaningless otherwise
12653         if (ent == r_refdef.scene.worldentity)
12654                 RSurf_ActiveWorldEntity();
12655         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12656                 RSurf_ActiveModelEntity(ent, false, false, false);
12657         else if (prepass)
12658                 RSurf_ActiveModelEntity(ent, true, true, true);
12659         else if (depthonly)
12660         {
12661                 switch (vid.renderpath)
12662                 {
12663                 case RENDERPATH_GL20:
12664                 case RENDERPATH_D3D9:
12665                 case RENDERPATH_D3D10:
12666                 case RENDERPATH_D3D11:
12667                 case RENDERPATH_SOFT:
12668                 case RENDERPATH_GLES2:
12669                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12670                         break;
12671                 case RENDERPATH_GL11:
12672                 case RENDERPATH_GL13:
12673                 case RENDERPATH_GLES1:
12674                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12675                         break;
12676                 }
12677         }
12678         else
12679         {
12680                 switch (vid.renderpath)
12681                 {
12682                 case RENDERPATH_GL20:
12683                 case RENDERPATH_D3D9:
12684                 case RENDERPATH_D3D10:
12685                 case RENDERPATH_D3D11:
12686                 case RENDERPATH_SOFT:
12687                 case RENDERPATH_GLES2:
12688                         RSurf_ActiveModelEntity(ent, true, true, false);
12689                         break;
12690                 case RENDERPATH_GL11:
12691                 case RENDERPATH_GL13:
12692                 case RENDERPATH_GLES1:
12693                         RSurf_ActiveModelEntity(ent, true, false, false);
12694                         break;
12695                 }
12696         }
12697
12698         surfaces = model->data_surfaces;
12699         update = model->brushq1.lightmapupdateflags;
12700
12701         // update light styles
12702         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12703         {
12704                 model_brush_lightstyleinfo_t *style;
12705                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12706                 {
12707                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12708                         {
12709                                 int *list = style->surfacelist;
12710                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12711                                 for (j = 0;j < style->numsurfaces;j++)
12712                                         update[list[j]] = true;
12713                         }
12714                 }
12715         }
12716
12717         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12718
12719         if (debug)
12720         {
12721                 R_DrawDebugModel();
12722                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12723                 return;
12724         }
12725
12726         rsurface.lightmaptexture = NULL;
12727         rsurface.deluxemaptexture = NULL;
12728         rsurface.uselightmaptexture = false;
12729         rsurface.texture = NULL;
12730         rsurface.rtlight = NULL;
12731         numsurfacelist = 0;
12732         // add visible surfaces to draw list
12733         for (i = 0;i < model->nummodelsurfaces;i++)
12734                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12735         // don't do anything if there were no surfaces
12736         if (!numsurfacelist)
12737         {
12738                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12739                 return;
12740         }
12741         // update lightmaps if needed
12742         if (update)
12743         {
12744                 int updated = 0;
12745                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12746                 {
12747                         if (update[j])
12748                         {
12749                                 updated++;
12750                                 R_BuildLightMap(ent, surfaces + j);
12751                         }
12752                 }
12753         }
12754
12755         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12756
12757         // add to stats if desired
12758         if (r_speeds.integer && !skysurfaces && !depthonly)
12759         {
12760                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12761                 for (j = 0;j < numsurfacelist;j++)
12762                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12763         }
12764
12765         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12766 }
12767
12768 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12769 {
12770         static texture_t texture;
12771         static msurface_t surface;
12772         const msurface_t *surfacelist = &surface;
12773
12774         // fake enough texture and surface state to render this geometry
12775
12776         texture.update_lastrenderframe = -1; // regenerate this texture
12777         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12778         texture.basealpha = 1.0f;
12779         texture.currentskinframe = skinframe;
12780         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12781         texture.offsetmapping = OFFSETMAPPING_OFF;
12782         texture.offsetscale = 1;
12783         texture.specularscalemod = 1;
12784         texture.specularpowermod = 1;
12785         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12786         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12787         // JUST GREP FOR "specularscalemod = 1".
12788
12789         surface.texture = &texture;
12790         surface.num_triangles = numtriangles;
12791         surface.num_firsttriangle = firsttriangle;
12792         surface.num_vertices = numvertices;
12793         surface.num_firstvertex = firstvertex;
12794
12795         // now render it
12796         rsurface.texture = R_GetCurrentTexture(surface.texture);
12797         rsurface.lightmaptexture = NULL;
12798         rsurface.deluxemaptexture = NULL;
12799         rsurface.uselightmaptexture = false;
12800         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12801 }
12802
12803 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)
12804 {
12805         static msurface_t surface;
12806         const msurface_t *surfacelist = &surface;
12807
12808         // fake enough texture and surface state to render this geometry
12809         surface.texture = texture;
12810         surface.num_triangles = numtriangles;
12811         surface.num_firsttriangle = firsttriangle;
12812         surface.num_vertices = numvertices;
12813         surface.num_firstvertex = firstvertex;
12814
12815         // now render it
12816         rsurface.texture = R_GetCurrentTexture(surface.texture);
12817         rsurface.lightmaptexture = NULL;
12818         rsurface.deluxemaptexture = NULL;
12819         rsurface.uselightmaptexture = false;
12820         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12821 }