]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Overhauled shadowmap rendering to use an atlas texture, this is overall a speed loss...
[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 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
642
643 //=======================================================================================================================================================
644
645 typedef struct shaderpermutationinfo_s
646 {
647         const char *pretext;
648         const char *name;
649 }
650 shaderpermutationinfo_t;
651
652 typedef struct shadermodeinfo_s
653 {
654         const char *filename;
655         const char *pretext;
656         const char *name;
657 }
658 shadermodeinfo_t;
659
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
662 {
663         {"#define USEDIFFUSE\n", " diffuse"},
664         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665         {"#define USEVIEWTINT\n", " viewtint"},
666         {"#define USECOLORMAPPING\n", " colormapping"},
667         {"#define USESATURATION\n", " saturation"},
668         {"#define USEFOGINSIDE\n", " foginside"},
669         {"#define USEFOGOUTSIDE\n", " fogoutside"},
670         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672         {"#define USEGAMMARAMPS\n", " gammaramps"},
673         {"#define USECUBEFILTER\n", " cubefilter"},
674         {"#define USEGLOW\n", " glow"},
675         {"#define USEBLOOM\n", " bloom"},
676         {"#define USESPECULAR\n", " specular"},
677         {"#define USEPOSTPROCESSING\n", " postprocessing"},
678         {"#define USEREFLECTION\n", " reflection"},
679         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685         {"#define USEALPHAKILL\n", " alphakill"},
686         {"#define USEREFLECTCUBE\n", " reflectcube"},
687         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688         {"#define USEBOUNCEGRID\n", " bouncegrid"},
689         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690         {"#define USETRIPPY\n", " trippy"},
691         {"#define USEDEPTHRGB\n", " depthrgb"},
692         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693         {"#define USESKELETAL\n", " skeletal"},
694         {"#define USEOCCLUDE\n", " occlude"}
695 };
696
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 };
718
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
720 {
721         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
738 };
739
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
742 {
743         /// hash lookup data
744         struct r_glsl_permutation_s *hashnext;
745         unsigned int mode;
746         unsigned int permutation;
747
748         /// indicates if we have tried compiling this permutation already
749         qboolean compiled;
750         /// 0 if compilation failed
751         int program;
752         // texture units assigned to each detected uniform
753         int tex_Texture_First;
754         int tex_Texture_Second;
755         int tex_Texture_GammaRamps;
756         int tex_Texture_Normal;
757         int tex_Texture_Color;
758         int tex_Texture_Gloss;
759         int tex_Texture_Glow;
760         int tex_Texture_SecondaryNormal;
761         int tex_Texture_SecondaryColor;
762         int tex_Texture_SecondaryGloss;
763         int tex_Texture_SecondaryGlow;
764         int tex_Texture_Pants;
765         int tex_Texture_Shirt;
766         int tex_Texture_FogHeightTexture;
767         int tex_Texture_FogMask;
768         int tex_Texture_Lightmap;
769         int tex_Texture_Deluxemap;
770         int tex_Texture_Attenuation;
771         int tex_Texture_Cube;
772         int tex_Texture_Refraction;
773         int tex_Texture_Reflection;
774         int tex_Texture_ShadowMap2D;
775         int tex_Texture_CubeProjection;
776         int tex_Texture_ScreenNormalMap;
777         int tex_Texture_ScreenDiffuse;
778         int tex_Texture_ScreenSpecular;
779         int tex_Texture_ReflectMask;
780         int tex_Texture_ReflectCube;
781         int tex_Texture_BounceGrid;
782         /// locations of detected uniforms in program object, or -1 if not found
783         int loc_Texture_First;
784         int loc_Texture_Second;
785         int loc_Texture_GammaRamps;
786         int loc_Texture_Normal;
787         int loc_Texture_Color;
788         int loc_Texture_Gloss;
789         int loc_Texture_Glow;
790         int loc_Texture_SecondaryNormal;
791         int loc_Texture_SecondaryColor;
792         int loc_Texture_SecondaryGloss;
793         int loc_Texture_SecondaryGlow;
794         int loc_Texture_Pants;
795         int loc_Texture_Shirt;
796         int loc_Texture_FogHeightTexture;
797         int loc_Texture_FogMask;
798         int loc_Texture_Lightmap;
799         int loc_Texture_Deluxemap;
800         int loc_Texture_Attenuation;
801         int loc_Texture_Cube;
802         int loc_Texture_Refraction;
803         int loc_Texture_Reflection;
804         int loc_Texture_ShadowMap2D;
805         int loc_Texture_CubeProjection;
806         int loc_Texture_ScreenNormalMap;
807         int loc_Texture_ScreenDiffuse;
808         int loc_Texture_ScreenSpecular;
809         int loc_Texture_ReflectMask;
810         int loc_Texture_ReflectCube;
811         int loc_Texture_BounceGrid;
812         int loc_Alpha;
813         int loc_BloomBlur_Parameters;
814         int loc_ClientTime;
815         int loc_Color_Ambient;
816         int loc_Color_Diffuse;
817         int loc_Color_Specular;
818         int loc_Color_Glow;
819         int loc_Color_Pants;
820         int loc_Color_Shirt;
821         int loc_DeferredColor_Ambient;
822         int loc_DeferredColor_Diffuse;
823         int loc_DeferredColor_Specular;
824         int loc_DeferredMod_Diffuse;
825         int loc_DeferredMod_Specular;
826         int loc_DistortScaleRefractReflect;
827         int loc_EyePosition;
828         int loc_FogColor;
829         int loc_FogHeightFade;
830         int loc_FogPlane;
831         int loc_FogPlaneViewDist;
832         int loc_FogRangeRecip;
833         int loc_LightColor;
834         int loc_LightDir;
835         int loc_LightPosition;
836         int loc_OffsetMapping_ScaleSteps;
837         int loc_OffsetMapping_LodDistance;
838         int loc_OffsetMapping_Bias;
839         int loc_PixelSize;
840         int loc_ReflectColor;
841         int loc_ReflectFactor;
842         int loc_ReflectOffset;
843         int loc_RefractColor;
844         int loc_Saturation;
845         int loc_ScreenCenterRefractReflect;
846         int loc_ScreenScaleRefractReflect;
847         int loc_ScreenToDepth;
848         int loc_ShadowMap_Parameters;
849         int loc_ShadowMap_TextureScale;
850         int loc_SpecularPower;
851         int loc_Skeletal_Transform12;
852         int loc_UserVec1;
853         int loc_UserVec2;
854         int loc_UserVec3;
855         int loc_UserVec4;
856         int loc_ViewTintColor;
857         int loc_ViewToLight;
858         int loc_ModelToLight;
859         int loc_TexMatrix;
860         int loc_BackgroundTexMatrix;
861         int loc_ModelViewProjectionMatrix;
862         int loc_ModelViewMatrix;
863         int loc_PixelToScreenTexCoord;
864         int loc_ModelToReflectCube;
865         int loc_ShadowMapMatrix;
866         int loc_BloomColorSubtract;
867         int loc_NormalmapScrollBlend;
868         int loc_BounceGridMatrix;
869         int loc_BounceGridIntensity;
870         /// uniform block bindings
871         int ubibind_Skeletal_Transform12_UniformBlock;
872         /// uniform block indices
873         int ubiloc_Skeletal_Transform12_UniformBlock;
874 }
875 r_glsl_permutation_t;
876
877 #define SHADERPERMUTATION_HASHSIZE 256
878
879
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
882 enum
883 {
884         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
890         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
892         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
898 };
899 #define SHADERSTATICPARMS_COUNT 14
900
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
903
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
906
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
910 {
911         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
914
915         // detect all
916         if (r_glsl_saturation_redcompensate.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918         if (r_glsl_vertextextureblend_usebothalphas.integer)
919                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920         if (r_shadow_glossexact.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922         if (r_glsl_postprocess.integer)
923         {
924                 if (r_glsl_postprocess_uservec1_enable.integer)
925                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926                 if (r_glsl_postprocess_uservec2_enable.integer)
927                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928                 if (r_glsl_postprocess_uservec3_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930                 if (r_glsl_postprocess_uservec4_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
932         }
933         if (r_fxaa.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
937
938         if (r_shadow_shadowmapsampler)
939                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940         if (r_shadow_shadowmappcf > 1)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942         else if (r_shadow_shadowmappcf)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944         if (r_celshading.integer)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946         if (r_celoutlines.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
948
949         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
950 }
951
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
955         else \
956                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
958 {
959         shaderstaticparms_count = 0;
960
961         // emit all
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
976 }
977
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
984
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
986 {
987         //unsigned int hashdepth = 0;
988         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989         r_glsl_permutation_t *p;
990         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
991         {
992                 if (p->mode == mode && p->permutation == permutation)
993                 {
994                         //if (hashdepth > 10)
995                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996                         return p;
997                 }
998                 //hashdepth++;
999         }
1000         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1001         p->mode = mode;
1002         p->permutation = permutation;
1003         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004         r_glsl_permutationhash[mode][hashindex] = p;
1005         //if (hashdepth > 10)
1006         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1007         return p;
1008 }
1009
1010 static char *R_ShaderStrCat(const char **strings)
1011 {
1012         char *string, *s;
1013         const char **p = strings;
1014         const char *t;
1015         size_t len = 0;
1016         for (p = strings;(t = *p);p++)
1017                 len += strlen(t);
1018         len++;
1019         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1020         len = 0;
1021         for (p = strings;(t = *p);p++)
1022         {
1023                 len = strlen(t);
1024                 memcpy(s, t, len);
1025                 s += len;
1026         }
1027         *s = 0;
1028         return string;
1029 }
1030
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1032 {
1033         char *shaderstring;
1034         if (!filename || !filename[0])
1035                 return NULL;
1036         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037         if (!strcmp(filename, "glsl/default.glsl"))
1038         {
1039                 if (builtinonly)
1040                         return R_ShaderStrCat(builtinshaderstrings);
1041                 if (!glslshaderstring)
1042                 {
1043                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044                         if (glslshaderstring)
1045                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046                         else
1047                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1048                 }
1049                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051                 return shaderstring;
1052         }
1053         if (!strcmp(filename, "hlsl/default.hlsl"))
1054         {
1055                 if (builtinonly)
1056                         return R_ShaderStrCat(builtinhlslshaderstrings);
1057                 if (!hlslshaderstring)
1058                 {
1059                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060                         if (hlslshaderstring)
1061                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1062                         else
1063                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1064                 }
1065                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067                 return shaderstring;
1068         }
1069         // we don't have builtin strings for any other files
1070         if (builtinonly)
1071                 return NULL;
1072         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("from disk %s... ", filename);
1077                 return shaderstring;
1078         }
1079         return shaderstring;
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127
1128         // the first pretext is which type of shader to compile as
1129         // (later these will all be bound together as a program object)
1130         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1133
1134         // the second pretext is the mode (for example a light source)
1135         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1139
1140         // now add all the permutation pretexts
1141         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1142         {
1143                 if (permutation & (1<<i))
1144                 {
1145                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1149                 }
1150                 else
1151                 {
1152                         // keep line numbers correct
1153                         vertstrings_list[vertstrings_count++] = "\n";
1154                         geomstrings_list[geomstrings_count++] = "\n";
1155                         fragstrings_list[fragstrings_count++] = "\n";
1156                 }
1157         }
1158
1159         // add static parms
1160         R_CompileShader_AddStaticParms(mode, permutation);
1161         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162         vertstrings_count += shaderstaticparms_count;
1163         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164         geomstrings_count += shaderstaticparms_count;
1165         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166         fragstrings_count += shaderstaticparms_count;
1167
1168         // now append the shader text itself
1169         vertstrings_list[vertstrings_count++] = sourcestring;
1170         geomstrings_list[geomstrings_count++] = sourcestring;
1171         fragstrings_list[fragstrings_count++] = sourcestring;
1172
1173         // compile the shader program
1174         if (vertstrings_count + geomstrings_count + fragstrings_count)
1175                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1176         if (p->program)
1177         {
1178                 CHECKGLERROR
1179                 qglUseProgram(p->program);CHECKGLERROR
1180                 // look up all the uniform variable names we care about, so we don't
1181                 // have to look them up every time we set them
1182
1183 #if 0
1184                 // debugging aid
1185                 {
1186                         GLint activeuniformindex = 0;
1187                         GLint numactiveuniforms = 0;
1188                         char uniformname[128];
1189                         GLsizei uniformnamelength = 0;
1190                         GLint uniformsize = 0;
1191                         GLenum uniformtype = 0;
1192                         memset(uniformname, 0, sizeof(uniformname));
1193                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1196                         {
1197                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1199                         }
1200                 }
1201 #endif
1202
1203                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1204                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1205                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1207                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1208                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1209                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1210                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1215                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1216                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1218                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1222                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1223                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1224                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1233                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1235                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1236                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1237                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1238                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1239                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1240                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1241                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1248                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1249                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1250                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1251                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1253                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1254                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1255                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1256                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1260                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1261                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1262                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1263                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1264                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1265                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1268                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1271                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1272                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1273                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1274                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1275                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1276                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1277                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1278                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1279                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289                 // initialize the samplers to refer to the texture units we use
1290                 p->tex_Texture_First = -1;
1291                 p->tex_Texture_Second = -1;
1292                 p->tex_Texture_GammaRamps = -1;
1293                 p->tex_Texture_Normal = -1;
1294                 p->tex_Texture_Color = -1;
1295                 p->tex_Texture_Gloss = -1;
1296                 p->tex_Texture_Glow = -1;
1297                 p->tex_Texture_SecondaryNormal = -1;
1298                 p->tex_Texture_SecondaryColor = -1;
1299                 p->tex_Texture_SecondaryGloss = -1;
1300                 p->tex_Texture_SecondaryGlow = -1;
1301                 p->tex_Texture_Pants = -1;
1302                 p->tex_Texture_Shirt = -1;
1303                 p->tex_Texture_FogHeightTexture = -1;
1304                 p->tex_Texture_FogMask = -1;
1305                 p->tex_Texture_Lightmap = -1;
1306                 p->tex_Texture_Deluxemap = -1;
1307                 p->tex_Texture_Attenuation = -1;
1308                 p->tex_Texture_Cube = -1;
1309                 p->tex_Texture_Refraction = -1;
1310                 p->tex_Texture_Reflection = -1;
1311                 p->tex_Texture_ShadowMap2D = -1;
1312                 p->tex_Texture_CubeProjection = -1;
1313                 p->tex_Texture_ScreenNormalMap = -1;
1314                 p->tex_Texture_ScreenDiffuse = -1;
1315                 p->tex_Texture_ScreenSpecular = -1;
1316                 p->tex_Texture_ReflectMask = -1;
1317                 p->tex_Texture_ReflectCube = -1;
1318                 p->tex_Texture_BounceGrid = -1;
1319                 // bind the texture samplers in use
1320                 sampler = 0;
1321                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1322                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1323                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1324                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1325                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1326                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1327                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1328                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1330                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1331                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1332                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1333                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1334                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1336                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1337                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1338                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1339                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1340                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1341                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1342                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1343                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1344                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1346                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1347                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1348                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1349                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1350                 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352                 if (vid.support.arb_uniform_buffer_object)
1353                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1354                 else
1355 #endif
1356                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357                 // clear the uniform block bindings
1358                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359                 // bind the uniform blocks in use
1360                 ubibind = 0;
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1363 #endif
1364                 // we're done compiling and setting up the shader, at least until it is used
1365                 CHECKGLERROR
1366                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1367         }
1368         else
1369                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1370
1371         // free the strings
1372         if (sourcestring)
1373                 Mem_Free(sourcestring);
1374 }
1375
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1377 {
1378         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379         if (r_glsl_permutation != perm)
1380         {
1381                 r_glsl_permutation = perm;
1382                 if (!r_glsl_permutation->program)
1383                 {
1384                         if (!r_glsl_permutation->compiled)
1385                         {
1386                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1388                         }
1389                         if (!r_glsl_permutation->program)
1390                         {
1391                                 // remove features until we find a valid permutation
1392                                 int i;
1393                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1394                                 {
1395                                         // reduce i more quickly whenever it would not remove any bits
1396                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397                                         if (!(permutation & j))
1398                                                 continue;
1399                                         permutation -= j;
1400                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401                                         if (!r_glsl_permutation->compiled)
1402                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1403                                         if (r_glsl_permutation->program)
1404                                                 break;
1405                                 }
1406                                 if (i >= SHADERPERMUTATION_COUNT)
1407                                 {
1408                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410                                         qglUseProgram(0);CHECKGLERROR
1411                                         return; // no bit left to clear, entire mode is broken
1412                                 }
1413                         }
1414                 }
1415                 CHECKGLERROR
1416                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1417         }
1418         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1421         CHECKGLERROR
1422 }
1423
1424 #ifdef SUPPORTD3D
1425
1426 #ifdef SUPPORTD3D
1427 #include <d3d9.h>
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1430 #endif
1431
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1434 {
1435         /// hash lookup data
1436         struct r_hlsl_permutation_s *hashnext;
1437         unsigned int mode;
1438         unsigned int permutation;
1439
1440         /// indicates if we have tried compiling this permutation already
1441         qboolean compiled;
1442         /// NULL if compilation failed
1443         IDirect3DVertexShader9 *vertexshader;
1444         IDirect3DPixelShader9 *pixelshader;
1445 }
1446 r_hlsl_permutation_t;
1447
1448 typedef enum D3DVSREGISTER_e
1449 {
1450         D3DVSREGISTER_TexMatrix = 0, // float4x4
1451         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455         D3DVSREGISTER_ModelToLight = 20, // float4x4
1456         D3DVSREGISTER_EyePosition = 24,
1457         D3DVSREGISTER_FogPlane = 25,
1458         D3DVSREGISTER_LightDir = 26,
1459         D3DVSREGISTER_LightPosition = 27,
1460 }
1461 D3DVSREGISTER_t;
1462
1463 typedef enum D3DPSREGISTER_e
1464 {
1465         D3DPSREGISTER_Alpha = 0,
1466         D3DPSREGISTER_BloomBlur_Parameters = 1,
1467         D3DPSREGISTER_ClientTime = 2,
1468         D3DPSREGISTER_Color_Ambient = 3,
1469         D3DPSREGISTER_Color_Diffuse = 4,
1470         D3DPSREGISTER_Color_Specular = 5,
1471         D3DPSREGISTER_Color_Glow = 6,
1472         D3DPSREGISTER_Color_Pants = 7,
1473         D3DPSREGISTER_Color_Shirt = 8,
1474         D3DPSREGISTER_DeferredColor_Ambient = 9,
1475         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476         D3DPSREGISTER_DeferredColor_Specular = 11,
1477         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478         D3DPSREGISTER_DeferredMod_Specular = 13,
1479         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480         D3DPSREGISTER_EyePosition = 15, // unused
1481         D3DPSREGISTER_FogColor = 16,
1482         D3DPSREGISTER_FogHeightFade = 17,
1483         D3DPSREGISTER_FogPlane = 18,
1484         D3DPSREGISTER_FogPlaneViewDist = 19,
1485         D3DPSREGISTER_FogRangeRecip = 20,
1486         D3DPSREGISTER_LightColor = 21,
1487         D3DPSREGISTER_LightDir = 22, // unused
1488         D3DPSREGISTER_LightPosition = 23,
1489         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490         D3DPSREGISTER_PixelSize = 25,
1491         D3DPSREGISTER_ReflectColor = 26,
1492         D3DPSREGISTER_ReflectFactor = 27,
1493         D3DPSREGISTER_ReflectOffset = 28,
1494         D3DPSREGISTER_RefractColor = 29,
1495         D3DPSREGISTER_Saturation = 30,
1496         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498         D3DPSREGISTER_ScreenToDepth = 33,
1499         D3DPSREGISTER_ShadowMap_Parameters = 34,
1500         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501         D3DPSREGISTER_SpecularPower = 36,
1502         D3DPSREGISTER_UserVec1 = 37,
1503         D3DPSREGISTER_UserVec2 = 38,
1504         D3DPSREGISTER_UserVec3 = 39,
1505         D3DPSREGISTER_UserVec4 = 40,
1506         D3DPSREGISTER_ViewTintColor = 41,
1507         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508         D3DPSREGISTER_BloomColorSubtract = 43,
1509         D3DPSREGISTER_ViewToLight = 44, // float4x4
1510         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511         D3DPSREGISTER_NormalmapScrollBlend = 52,
1512         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513         D3DPSREGISTER_OffsetMapping_Bias = 54,
1514         // next at 54
1515 }
1516 D3DPSREGISTER_t;
1517
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1524
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1526 {
1527         //unsigned int hashdepth = 0;
1528         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529         r_hlsl_permutation_t *p;
1530         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1531         {
1532                 if (p->mode == mode && p->permutation == permutation)
1533                 {
1534                         //if (hashdepth > 10)
1535                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536                         return p;
1537                 }
1538                 //hashdepth++;
1539         }
1540         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1541         p->mode = mode;
1542         p->permutation = permutation;
1543         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544         r_hlsl_permutationhash[mode][hashindex] = p;
1545         //if (hashdepth > 10)
1546         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1547         return p;
1548 }
1549
1550 #include <d3dx9.h>
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1553
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1555 {
1556         DWORD *vsbin = NULL;
1557         DWORD *psbin = NULL;
1558         fs_offset_t vsbinsize;
1559         fs_offset_t psbinsize;
1560 //      IDirect3DVertexShader9 *vs = NULL;
1561 //      IDirect3DPixelShader9 *ps = NULL;
1562         ID3DXBuffer *vslog = NULL;
1563         ID3DXBuffer *vsbuffer = NULL;
1564         ID3DXConstantTable *vsconstanttable = NULL;
1565         ID3DXBuffer *pslog = NULL;
1566         ID3DXBuffer *psbuffer = NULL;
1567         ID3DXConstantTable *psconstanttable = NULL;
1568         int vsresult = 0;
1569         int psresult = 0;
1570         char temp[MAX_INPUTLINE];
1571         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1572         char vabuf[1024];
1573         qboolean debugshader = gl_paranoid.integer != 0;
1574         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1576         if (!debugshader)
1577         {
1578                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1580         }
1581         if ((!vsbin && vertstring) || (!psbin && fragstring))
1582         {
1583                 const char* dllnames_d3dx9 [] =
1584                 {
1585                         "d3dx9_43.dll",
1586                         "d3dx9_42.dll",
1587                         "d3dx9_41.dll",
1588                         "d3dx9_40.dll",
1589                         "d3dx9_39.dll",
1590                         "d3dx9_38.dll",
1591                         "d3dx9_37.dll",
1592                         "d3dx9_36.dll",
1593                         "d3dx9_35.dll",
1594                         "d3dx9_34.dll",
1595                         "d3dx9_33.dll",
1596                         "d3dx9_32.dll",
1597                         "d3dx9_31.dll",
1598                         "d3dx9_30.dll",
1599                         "d3dx9_29.dll",
1600                         "d3dx9_28.dll",
1601                         "d3dx9_27.dll",
1602                         "d3dx9_26.dll",
1603                         "d3dx9_25.dll",
1604                         "d3dx9_24.dll",
1605                         NULL
1606                 };
1607                 dllhandle_t d3dx9_dll = NULL;
1608                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611                 dllfunction_t d3dx9_dllfuncs[] =
1612                 {
1613                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1614                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1615                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1616                         {NULL, NULL}
1617                 };
1618                 // 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...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1624 #else
1625 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p)            (p)->Release()
1628 #endif
1629 #endif
1630                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1631                 {
1632                         DWORD shaderflags = 0;
1633                         if (debugshader)
1634                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637                         if (vertstring && vertstring[0])
1638                         {
1639                                 if (debugshader)
1640                                 {
1641                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1643                                 }
1644                                 else
1645                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1646                                 if (vsbuffer)
1647                                 {
1648                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651                                         ID3DXBuffer_Release(vsbuffer);
1652                                 }
1653                                 if (vslog)
1654                                 {
1655                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657                                         ID3DXBuffer_Release(vslog);
1658                                 }
1659                         }
1660                         if (fragstring && fragstring[0])
1661                         {
1662                                 if (debugshader)
1663                                 {
1664                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1666                                 }
1667                                 else
1668                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1669                                 if (psbuffer)
1670                                 {
1671                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674                                         ID3DXBuffer_Release(psbuffer);
1675                                 }
1676                                 if (pslog)
1677                                 {
1678                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680                                         ID3DXBuffer_Release(pslog);
1681                                 }
1682                         }
1683                         Sys_UnloadLibrary(&d3dx9_dll);
1684                 }
1685                 else
1686                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1687         }
1688         if (vsbin && psbin)
1689         {
1690                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691                 if (FAILED(vsresult))
1692                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694                 if (FAILED(psresult))
1695                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1696         }
1697         // free the shader data
1698         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1700 }
1701
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1703 {
1704         int i;
1705         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706         int vertstring_length = 0;
1707         int geomstring_length = 0;
1708         int fragstring_length = 0;
1709         char *t;
1710         char *sourcestring;
1711         char *vertstring, *geomstring, *fragstring;
1712         char permutationname[256];
1713         char cachename[256];
1714         int vertstrings_count = 0;
1715         int geomstrings_count = 0;
1716         int fragstrings_count = 0;
1717         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1720
1721         if (p->compiled)
1722                 return;
1723         p->compiled = true;
1724         p->vertexshader = NULL;
1725         p->pixelshader = NULL;
1726
1727         permutationname[0] = 0;
1728         cachename[0] = 0;
1729         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1730
1731         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732         strlcat(cachename, "hlsl/", sizeof(cachename));
1733
1734         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735         vertstrings_count = 0;
1736         geomstrings_count = 0;
1737         fragstrings_count = 0;
1738         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1741
1742         // the first pretext is which type of shader to compile as
1743         // (later these will all be bound together as a program object)
1744         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1747
1748         // the second pretext is the mode (for example a light source)
1749         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753         strlcat(cachename, modeinfo->name, sizeof(cachename));
1754
1755         // now add all the permutation pretexts
1756         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1757         {
1758                 if (permutation & (1<<i))
1759                 {
1760                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1765                 }
1766                 else
1767                 {
1768                         // keep line numbers correct
1769                         vertstrings_list[vertstrings_count++] = "\n";
1770                         geomstrings_list[geomstrings_count++] = "\n";
1771                         fragstrings_list[fragstrings_count++] = "\n";
1772                 }
1773         }
1774
1775         // add static parms
1776         R_CompileShader_AddStaticParms(mode, permutation);
1777         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778         vertstrings_count += shaderstaticparms_count;
1779         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780         geomstrings_count += shaderstaticparms_count;
1781         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782         fragstrings_count += shaderstaticparms_count;
1783
1784         // replace spaces in the cachename with _ characters
1785         for (i = 0;cachename[i];i++)
1786                 if (cachename[i] == ' ')
1787                         cachename[i] = '_';
1788
1789         // now append the shader text itself
1790         vertstrings_list[vertstrings_count++] = sourcestring;
1791         geomstrings_list[geomstrings_count++] = sourcestring;
1792         fragstrings_list[fragstrings_count++] = sourcestring;
1793
1794         vertstring_length = 0;
1795         for (i = 0;i < vertstrings_count;i++)
1796                 vertstring_length += (int)strlen(vertstrings_list[i]);
1797         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1800
1801         geomstring_length = 0;
1802         for (i = 0;i < geomstrings_count;i++)
1803                 geomstring_length += (int)strlen(geomstrings_list[i]);
1804         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1807
1808         fragstring_length = 0;
1809         for (i = 0;i < fragstrings_count;i++)
1810                 fragstring_length += (int)strlen(fragstrings_list[i]);
1811         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1814
1815         // try to load the cached shader, or generate one
1816         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1817
1818         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1820         else
1821                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1822
1823         // free the strings
1824         if (vertstring)
1825                 Mem_Free(vertstring);
1826         if (geomstring)
1827                 Mem_Free(geomstring);
1828         if (fragstring)
1829                 Mem_Free(fragstring);
1830         if (sourcestring)
1831                 Mem_Free(sourcestring);
1832 }
1833
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 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);}
1837 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);}
1838 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);}
1839 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);}
1840
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 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);}
1844 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);}
1845 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);}
1846 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);}
1847
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1849 {
1850         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851         if (r_hlsl_permutation != perm)
1852         {
1853                 r_hlsl_permutation = perm;
1854                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1855                 {
1856                         if (!r_hlsl_permutation->compiled)
1857                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1858                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1859                         {
1860                                 // remove features until we find a valid permutation
1861                                 int i;
1862                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863                                 {
1864                                         // reduce i more quickly whenever it would not remove any bits
1865                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866                                         if (!(permutation & j))
1867                                                 continue;
1868                                         permutation -= j;
1869                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870                                         if (!r_hlsl_permutation->compiled)
1871                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1872                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1873                                                 break;
1874                                 }
1875                                 if (i >= SHADERPERMUTATION_COUNT)
1876                                 {
1877                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879                                         return; // no bit left to clear, entire mode is broken
1880                                 }
1881                         }
1882                 }
1883                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1885         }
1886         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1889 }
1890 #endif
1891
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1893 {
1894         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1898 }
1899
1900 void R_GLSL_Restart_f(void)
1901 {
1902         unsigned int i, limit;
1903         if (glslshaderstring)
1904                 Mem_Free(glslshaderstring);
1905         glslshaderstring = NULL;
1906         if (hlslshaderstring)
1907                 Mem_Free(hlslshaderstring);
1908         hlslshaderstring = NULL;
1909         switch(vid.renderpath)
1910         {
1911         case RENDERPATH_D3D9:
1912 #ifdef SUPPORTD3D
1913                 {
1914                         r_hlsl_permutation_t *p;
1915                         r_hlsl_permutation = NULL;
1916                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917                         for (i = 0;i < limit;i++)
1918                         {
1919                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1920                                 {
1921                                         if (p->vertexshader)
1922                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1923                                         if (p->pixelshader)
1924                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1925                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1926                                 }
1927                         }
1928                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1929                 }
1930 #endif
1931                 break;
1932         case RENDERPATH_D3D10:
1933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_D3D11:
1936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_GL20:
1939         case RENDERPATH_GLES2:
1940                 {
1941                         r_glsl_permutation_t *p;
1942                         r_glsl_permutation = NULL;
1943                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944                         for (i = 0;i < limit;i++)
1945                         {
1946                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1947                                 {
1948                                         GL_Backend_FreeProgram(p->program);
1949                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1950                                 }
1951                         }
1952                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1953                 }
1954                 break;
1955         case RENDERPATH_GL11:
1956         case RENDERPATH_GL13:
1957         case RENDERPATH_GLES1:
1958                 break;
1959         case RENDERPATH_SOFT:
1960                 break;
1961         }
1962 }
1963
1964 static void R_GLSL_DumpShader_f(void)
1965 {
1966         int i, language, mode, dupe;
1967         char *text;
1968         shadermodeinfo_t *modeinfo;
1969         qfile_t *file;
1970
1971         for (language = 0;language < 2;language++)
1972         {
1973                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1975                 {
1976                         // don't dump the same file multiple times (most or all shaders come from the same file)
1977                         for (dupe = mode - 1;dupe >= 0;dupe--)
1978                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1979                                         break;
1980                         if (dupe >= 0)
1981                                 continue;
1982                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1983                         if (!text)
1984                                 continue;
1985                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1986                         if (file)
1987                         {
1988                                 FS_Print(file, "/* The engine may define the following macros:\n");
1989                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1991                                         FS_Print(file, modeinfo[i].pretext);
1992                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1994                                 FS_Print(file, "*/\n");
1995                                 FS_Print(file, text);
1996                                 FS_Close(file);
1997                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1998                         }
1999                         else
2000                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2001                         Mem_Free(text);
2002                 }
2003         }
2004 }
2005
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2007 {
2008         unsigned int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         permutation |= SHADERPERMUTATION_VIEWTINT;
2012         if (first)
2013                 permutation |= SHADERPERMUTATION_DIFFUSE;
2014         if (second)
2015                 permutation |= SHADERPERMUTATION_SPECULAR;
2016         if (texturemode == GL_MODULATE)
2017                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018         else if (texturemode == GL_ADD)
2019                 permutation |= SHADERPERMUTATION_GLOW;
2020         else if (texturemode == GL_DECAL)
2021                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024         if (suppresstexalpha)
2025                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2026         if (!second)
2027                 texturemode = GL_MODULATE;
2028         if (vid.allowalphatocoverage)
2029                 GL_AlphaToCoverage(false);
2030         switch (vid.renderpath)
2031         {
2032         case RENDERPATH_D3D9:
2033 #ifdef SUPPORTD3D
2034                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035                 R_Mesh_TexBind(GL20TU_FIRST , first );
2036                 R_Mesh_TexBind(GL20TU_SECOND, second);
2037                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039 #endif
2040                 break;
2041         case RENDERPATH_D3D10:
2042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043                 break;
2044         case RENDERPATH_D3D11:
2045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046                 break;
2047         case RENDERPATH_GL20:
2048         case RENDERPATH_GLES2:
2049                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050                 if (r_glsl_permutation->tex_Texture_First >= 0)
2051                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2056                 break;
2057         case RENDERPATH_GL13:
2058         case RENDERPATH_GLES1:
2059                 R_Mesh_TexBind(0, first );
2060                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061                 R_Mesh_TexMatrix(0, NULL);
2062                 R_Mesh_TexBind(1, second);
2063                 if (second)
2064                 {
2065                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066                         R_Mesh_TexMatrix(1, NULL);
2067                 }
2068                 break;
2069         case RENDERPATH_GL11:
2070                 R_Mesh_TexBind(0, first );
2071                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072                 R_Mesh_TexMatrix(0, NULL);
2073                 break;
2074         case RENDERPATH_SOFT:
2075                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076                 R_Mesh_TexBind(GL20TU_FIRST , first );
2077                 R_Mesh_TexBind(GL20TU_SECOND, second);
2078                 break;
2079         }
2080 }
2081
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2083 {
2084         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2085 }
2086
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2088 {
2089         unsigned int permutation = 0;
2090         if (r_trippy.integer && !notrippy)
2091                 permutation |= SHADERPERMUTATION_TRIPPY;
2092         if (depthrgb)
2093                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2094         if (skeletal)
2095                 permutation |= SHADERPERMUTATION_SKELETAL;
2096
2097         if (vid.allowalphatocoverage)
2098                 GL_AlphaToCoverage(false);
2099         switch (vid.renderpath)
2100         {
2101         case RENDERPATH_D3D9:
2102 #ifdef SUPPORTD3D
2103                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #endif
2105                 break;
2106         case RENDERPATH_D3D10:
2107                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108                 break;
2109         case RENDERPATH_D3D11:
2110                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2111                 break;
2112         case RENDERPATH_GL20:
2113         case RENDERPATH_GLES2:
2114                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116                 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);
2117 #endif
2118                 break;
2119         case RENDERPATH_GL13:
2120         case RENDERPATH_GLES1:
2121                 R_Mesh_TexBind(0, 0);
2122                 R_Mesh_TexBind(1, 0);
2123                 break;
2124         case RENDERPATH_GL11:
2125                 R_Mesh_TexBind(0, 0);
2126                 break;
2127         case RENDERPATH_SOFT:
2128                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129                 break;
2130         }
2131 }
2132
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_modelshadowmap_texturescale[4];
2140 extern float r_shadow_modelshadowmap_parameters[4];
2141 extern float r_shadow_lightshadowmap_texturescale[4];
2142 extern float r_shadow_lightshadowmap_parameters[4];
2143 extern qboolean r_shadow_shadowmapvsdct;
2144 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2145 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2146 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2147 extern matrix4x4_t r_shadow_shadowmapmatrix;
2148 extern int r_shadow_prepass_width;
2149 extern int r_shadow_prepass_height;
2150 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2151 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2152 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2153 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2154
2155 #define BLENDFUNC_ALLOWS_COLORMOD      1
2156 #define BLENDFUNC_ALLOWS_FOG           2
2157 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2158 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2159 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2160 static int R_BlendFuncFlags(int src, int dst)
2161 {
2162         int r = 0;
2163
2164         // a blendfunc allows colormod if:
2165         // a) it can never keep the destination pixel invariant, or
2166         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2167         // this is to prevent unintended side effects from colormod
2168
2169         // a blendfunc allows fog if:
2170         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2171         // this is to prevent unintended side effects from fog
2172
2173         // these checks are the output of fogeval.pl
2174
2175         r |= BLENDFUNC_ALLOWS_COLORMOD;
2176         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2180         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2183         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2184         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2185         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2188         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2189         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2194         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2196         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197
2198         return r;
2199 }
2200
2201 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)
2202 {
2203         // select a permutation of the lighting shader appropriate to this
2204         // combination of texture, entity, light source, and fogging, only use the
2205         // minimum features necessary to avoid wasting rendering time in the
2206         // fragment shader on features that are not being used
2207         unsigned int permutation = 0;
2208         unsigned int mode = 0;
2209         int blendfuncflags;
2210         static float dummy_colormod[3] = {1, 1, 1};
2211         float *colormod = rsurface.colormod;
2212         float m16f[16];
2213         matrix4x4_t tempmatrix;
2214         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2215         if (r_trippy.integer && !notrippy)
2216                 permutation |= SHADERPERMUTATION_TRIPPY;
2217         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2218                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2219         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2220                 permutation |= SHADERPERMUTATION_OCCLUDE;
2221         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2222                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2223         if (rsurfacepass == RSURFPASS_BACKGROUND)
2224         {
2225                 // distorted background
2226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2227                 {
2228                         mode = SHADERMODE_WATER;
2229                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2230                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2231                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2232                         {
2233                                 // this is the right thing to do for wateralpha
2234                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2235                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2236                         }
2237                         else
2238                         {
2239                                 // this is the right thing to do for entity alpha
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                 }
2244                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2245                 {
2246                         mode = SHADERMODE_REFRACTION;
2247                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2248                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2249                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2251                 }
2252                 else
2253                 {
2254                         mode = SHADERMODE_GENERIC;
2255                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2256                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258                 }
2259                 if (vid.allowalphatocoverage)
2260                         GL_AlphaToCoverage(false);
2261         }
2262         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2263         {
2264                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2265                 {
2266                         switch(rsurface.texture->offsetmapping)
2267                         {
2268                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2269                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271                         case OFFSETMAPPING_OFF: break;
2272                         }
2273                 }
2274                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2275                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2276                 // normalmap (deferred prepass), may use alpha test on diffuse
2277                 mode = SHADERMODE_DEFERREDGEOMETRY;
2278                 GL_BlendFunc(GL_ONE, GL_ZERO);
2279                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2280                 if (vid.allowalphatocoverage)
2281                         GL_AlphaToCoverage(false);
2282         }
2283         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2284         {
2285                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2286                 {
2287                         switch(rsurface.texture->offsetmapping)
2288                         {
2289                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2290                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2292                         case OFFSETMAPPING_OFF: break;
2293                         }
2294                 }
2295                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2296                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2298                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2299                 // light source
2300                 mode = SHADERMODE_LIGHTSOURCE;
2301                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2302                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2303                 if (diffusescale > 0)
2304                         permutation |= SHADERPERMUTATION_DIFFUSE;
2305                 if (specularscale > 0)
2306                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2307                 if (r_refdef.fogenabled)
2308                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309                 if (rsurface.texture->colormapping)
2310                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2311                 if (r_shadow_usingshadowmap2d)
2312                 {
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314                         if(r_shadow_shadowmapvsdct)
2315                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2316
2317                         if (r_shadow_shadowmap2ddepthbuffer)
2318                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2319                 }
2320                 if (rsurface.texture->reflectmasktexture)
2321                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2322                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2323                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2324                 if (vid.allowalphatocoverage)
2325                         GL_AlphaToCoverage(false);
2326         }
2327         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2328         {
2329                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2330                 {
2331                         switch(rsurface.texture->offsetmapping)
2332                         {
2333                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2334                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2335                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2336                         case OFFSETMAPPING_OFF: break;
2337                         }
2338                 }
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2340                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2341                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2342                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2343                 // unshaded geometry (fullbright or ambient model lighting)
2344                 mode = SHADERMODE_FLATCOLOR;
2345                 ambientscale = diffusescale = specularscale = 0;
2346                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347                         permutation |= SHADERPERMUTATION_GLOW;
2348                 if (r_refdef.fogenabled)
2349                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350                 if (rsurface.texture->colormapping)
2351                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2352                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2353                 {
2354                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2356
2357                         if (r_shadow_shadowmap2ddepthbuffer)
2358                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2361                         permutation |= SHADERPERMUTATION_REFLECTION;
2362                 if (rsurface.texture->reflectmasktexture)
2363                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2364                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2366                 // when using alphatocoverage, we don't need alphakill
2367                 if (vid.allowalphatocoverage)
2368                 {
2369                         if (r_transparent_alphatocoverage.integer)
2370                         {
2371                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2372                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2373                         }
2374                         else
2375                                 GL_AlphaToCoverage(false);
2376                 }
2377         }
2378         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2379         {
2380                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2381                 {
2382                         switch(rsurface.texture->offsetmapping)
2383                         {
2384                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2385                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2387                         case OFFSETMAPPING_OFF: break;
2388                         }
2389                 }
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2391                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2392                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2393                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2394                 // directional model lighting
2395                 mode = SHADERMODE_LIGHTDIRECTION;
2396                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2397                         permutation |= SHADERPERMUTATION_GLOW;
2398                 permutation |= SHADERPERMUTATION_DIFFUSE;
2399                 if (specularscale > 0)
2400                         permutation |= SHADERPERMUTATION_SPECULAR;
2401                 if (r_refdef.fogenabled)
2402                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2403                 if (rsurface.texture->colormapping)
2404                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2405                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2406                 {
2407                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2408                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2409
2410                         if (r_shadow_shadowmap2ddepthbuffer)
2411                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2414                         permutation |= SHADERPERMUTATION_REFLECTION;
2415                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2416                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2417                 if (rsurface.texture->reflectmasktexture)
2418                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2419                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2420                 {
2421                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2422                         if (r_shadow_bouncegrid_state.directional)
2423                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2424                 }
2425                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427                 // when using alphatocoverage, we don't need alphakill
2428                 if (vid.allowalphatocoverage)
2429                 {
2430                         if (r_transparent_alphatocoverage.integer)
2431                         {
2432                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2433                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2434                         }
2435                         else
2436                                 GL_AlphaToCoverage(false);
2437                 }
2438         }
2439         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2440         {
2441                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2442                 {
2443                         switch(rsurface.texture->offsetmapping)
2444                         {
2445                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2446                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2447                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2448                         case OFFSETMAPPING_OFF: break;
2449                         }
2450                 }
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2452                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2454                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2455                 // ambient model lighting
2456                 mode = SHADERMODE_LIGHTDIRECTION;
2457                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2458                         permutation |= SHADERPERMUTATION_GLOW;
2459                 if (r_refdef.fogenabled)
2460                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2461                 if (rsurface.texture->colormapping)
2462                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2463                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2464                 {
2465                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2466                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2467
2468                         if (r_shadow_shadowmap2ddepthbuffer)
2469                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2470                 }
2471                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2472                         permutation |= SHADERPERMUTATION_REFLECTION;
2473                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2474                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2475                 if (rsurface.texture->reflectmasktexture)
2476                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2477                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2478                 {
2479                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2480                         if (r_shadow_bouncegrid_state.directional)
2481                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2482                 }
2483                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 // when using alphatocoverage, we don't need alphakill
2486                 if (vid.allowalphatocoverage)
2487                 {
2488                         if (r_transparent_alphatocoverage.integer)
2489                         {
2490                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2491                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2492                         }
2493                         else
2494                                 GL_AlphaToCoverage(false);
2495                 }
2496         }
2497         else
2498         {
2499                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2500                 {
2501                         switch(rsurface.texture->offsetmapping)
2502                         {
2503                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2504                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2505                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2506                         case OFFSETMAPPING_OFF: break;
2507                         }
2508                 }
2509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2510                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2511                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2512                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2513                 // lightmapped wall
2514                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2515                         permutation |= SHADERPERMUTATION_GLOW;
2516                 if (r_refdef.fogenabled)
2517                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2518                 if (rsurface.texture->colormapping)
2519                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2520                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2521                 {
2522                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2523                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2524
2525                         if (r_shadow_shadowmap2ddepthbuffer)
2526                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2527                 }
2528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2529                         permutation |= SHADERPERMUTATION_REFLECTION;
2530                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2531                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2532                 if (rsurface.texture->reflectmasktexture)
2533                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2534                 if (FAKELIGHT_ENABLED)
2535                 {
2536                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2537                         mode = SHADERMODE_FAKELIGHT;
2538                         permutation |= SHADERPERMUTATION_DIFFUSE;
2539                         if (specularscale > 0)
2540                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2541                 }
2542                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2543                 {
2544                         // deluxemapping (light direction texture)
2545                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2546                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2547                         else
2548                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2549                         permutation |= SHADERPERMUTATION_DIFFUSE;
2550                         if (specularscale > 0)
2551                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2552                 }
2553                 else if (r_glsl_deluxemapping.integer >= 2)
2554                 {
2555                         // fake deluxemapping (uniform light direction in tangentspace)
2556                         if (rsurface.uselightmaptexture)
2557                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2558                         else
2559                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2560                         permutation |= SHADERPERMUTATION_DIFFUSE;
2561                         if (specularscale > 0)
2562                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2563                 }
2564                 else if (rsurface.uselightmaptexture)
2565                 {
2566                         // ordinary lightmapping (q1bsp, q3bsp)
2567                         mode = SHADERMODE_LIGHTMAP;
2568                 }
2569                 else
2570                 {
2571                         // ordinary vertex coloring (q3bsp)
2572                         mode = SHADERMODE_VERTEXCOLOR;
2573                 }
2574                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2575                 {
2576                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2577                         if (r_shadow_bouncegrid_state.directional)
2578                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2579                 }
2580                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2581                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2582                 // when using alphatocoverage, we don't need alphakill
2583                 if (vid.allowalphatocoverage)
2584                 {
2585                         if (r_transparent_alphatocoverage.integer)
2586                         {
2587                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2588                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2589                         }
2590                         else
2591                                 GL_AlphaToCoverage(false);
2592                 }
2593         }
2594         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2595                 colormod = dummy_colormod;
2596         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2597                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2598         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2599                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2600         switch(vid.renderpath)
2601         {
2602         case RENDERPATH_D3D9:
2603 #ifdef SUPPORTD3D
2604                 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);
2605                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2606                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2607                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2608                 if (mode == SHADERMODE_LIGHTSOURCE)
2609                 {
2610                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2611                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2612                 }
2613                 else
2614                 {
2615                         if (mode == SHADERMODE_LIGHTDIRECTION)
2616                         {
2617                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2618                         }
2619                 }
2620                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2621                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2622                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2623                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2624                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2625
2626                 if (mode == SHADERMODE_LIGHTSOURCE)
2627                 {
2628                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2629                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2632                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2633
2634                         // additive passes are only darkened by fog, not tinted
2635                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2636                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2637                 }
2638                 else
2639                 {
2640                         if (mode == SHADERMODE_FLATCOLOR)
2641                         {
2642                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2643                         }
2644                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2645                         {
2646                                 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]);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2648                                 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);
2649                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2652                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2653                         }
2654                         else
2655                         {
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2658                                 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);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2660                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2661                         }
2662                         // additive passes are only darkened by fog, not tinted
2663                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2665                         else
2666                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2667                         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);
2668                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2669                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2670                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2671                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2672                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2673                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2674                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2675                         if (mode == SHADERMODE_WATER)
2676                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2677                 }
2678                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2679                 {
2680                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2681                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2682                 }
2683                 else
2684                 {
2685                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2686                         hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2687                 }
2688                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2689                 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));
2690                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2691                 if (rsurface.texture->pantstexture)
2692                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2693                 else
2694                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2695                 if (rsurface.texture->shirttexture)
2696                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2697                 else
2698                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2699                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2700                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2701                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2702                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2703                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2704                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2705                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2706                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2707                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2708                         );
2709                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2710                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2711                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2712                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2713
2714                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2715                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2716                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2717                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2718                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2719                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2720                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2721                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2722                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2723                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2724                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2725                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2726                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2727                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2728                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2729                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2730                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2731                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2732                 {
2733                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2734                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2735                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2736                 }
2737                 else
2738                 {
2739                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2740                 }
2741 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2742                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2743                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2744                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2745                 {
2746                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2747                         if (rsurface.rtlight)
2748                         {
2749                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2750                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2751                         }
2752                 }
2753 #endif
2754                 break;
2755         case RENDERPATH_D3D10:
2756                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2757                 break;
2758         case RENDERPATH_D3D11:
2759                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2760                 break;
2761         case RENDERPATH_GL20:
2762         case RENDERPATH_GLES2:
2763                 if (!vid.useinterleavedarrays)
2764                 {
2765                         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);
2766                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2767                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2768                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2769                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2770                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2771                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2772                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2773                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2774                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2775                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2776                 }
2777                 else
2778                 {
2779                         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);
2780                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2781                 }
2782                 // this has to be after RSurf_PrepareVerticesForBatch
2783                 if (rsurface.batchskeletaltransform3x4buffer)
2784                         permutation |= SHADERPERMUTATION_SKELETAL;
2785                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2786 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2787                 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);
2788 #endif
2789                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2790                 if (mode == SHADERMODE_LIGHTSOURCE)
2791                 {
2792                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2793                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2794                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2795                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2796                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2797                         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);
2798         
2799                         // additive passes are only darkened by fog, not tinted
2800                         if (r_glsl_permutation->loc_FogColor >= 0)
2801                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2802                         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);
2803                 }
2804                 else
2805                 {
2806                         if (mode == SHADERMODE_FLATCOLOR)
2807                         {
2808                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2809                         }
2810                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2811                         {
2812                                 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]);
2813                                 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]);
2814                                 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);
2815                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2816                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2817                                 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]);
2818                                 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]);
2819                         }
2820                         else
2821                         {
2822                                 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]);
2823                                 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]);
2824                                 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);
2825                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2826                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2827                         }
2828                         // additive passes are only darkened by fog, not tinted
2829                         if (r_glsl_permutation->loc_FogColor >= 0)
2830                         {
2831                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2832                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2833                                 else
2834                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2835                         }
2836                         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);
2837                         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]);
2838                         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]);
2839                         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]);
2840                         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]);
2841                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2842                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2843                         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);
2844                         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]);
2845                 }
2846                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2847                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2848                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2849                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2850                 {
2851                         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]);
2852                         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]);
2853                 }
2854                 else
2855                 {
2856                         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]);
2857                         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]);
2858                 }
2859
2860                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2861                 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));
2862                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2863                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2864                 {
2865                         if (rsurface.texture->pantstexture)
2866                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2867                         else
2868                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2869                 }
2870                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2871                 {
2872                         if (rsurface.texture->shirttexture)
2873                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2874                         else
2875                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2876                 }
2877                 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]);
2878                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2879                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2880                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2881                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2882                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2883                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2884                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2885                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2886                         );
2887                 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);
2888                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2889                 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]);
2890                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2891                 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);}
2892                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2893
2894                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2895                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2896                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2897                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2898                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2899                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2900                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2901                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2902                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2903                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2904                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2905                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2906                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2907                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2908                 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);
2909                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2910                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2911                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2912                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2913                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2914                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2915                 {
2916                         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);
2917                         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);
2918                         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);
2919                 }
2920                 else
2921                 {
2922                         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);
2923                 }
2924                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2925                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2926                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2927                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2928                 {
2929                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2930                         if (rsurface.rtlight)
2931                         {
2932                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2933                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2934                         }
2935                 }
2936                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2937                 CHECKGLERROR
2938                 break;
2939         case RENDERPATH_GL11:
2940         case RENDERPATH_GL13:
2941         case RENDERPATH_GLES1:
2942                 break;
2943         case RENDERPATH_SOFT:
2944                 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);
2945                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2946                 R_SetupShader_SetPermutationSoft(mode, permutation);
2947                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2948                 if (mode == SHADERMODE_LIGHTSOURCE)
2949                 {
2950                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2951                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2952                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2953                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2954                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2955                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2956         
2957                         // additive passes are only darkened by fog, not tinted
2958                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2959                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2960                 }
2961                 else
2962                 {
2963                         if (mode == SHADERMODE_FLATCOLOR)
2964                         {
2965                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2966                         }
2967                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2968                         {
2969                                 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]);
2970                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2971                                 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);
2972                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2973                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2974                                 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]);
2975                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2976                         }
2977                         else
2978                         {
2979                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2980                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2981                                 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);
2982                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2984                         }
2985                         // additive passes are only darkened by fog, not tinted
2986                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2987                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2988                         else
2989                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2990                         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);
2991                         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]);
2992                         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]);
2993                         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]);
2994                         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]);
2995                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2996                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2997                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2998                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2999                 }
3000                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3001                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3002                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3003                 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3004                 {
3005                         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]);
3006                         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]);
3007                 }
3008                 else
3009                 {
3010                         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]);
3011                         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]);
3012                 }
3013
3014                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3015                 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));
3016                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3017                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3018                 {
3019                         if (rsurface.texture->pantstexture)
3020                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3021                         else
3022                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3023                 }
3024                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3025                 {
3026                         if (rsurface.texture->shirttexture)
3027                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3028                         else
3029                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3030                 }
3031                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3032                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3033                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3034                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3035                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3036                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3037                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3038                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3039                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3040                         );
3041                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3042                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3043                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3045
3046                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3047                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3048                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3049                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3050                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3051                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3052                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3053                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3054                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3055                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3056                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3057                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3058                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3059                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3060                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3061                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3062                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3063                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3064                 {
3065                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3066                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3067                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3068                 }
3069                 else
3070                 {
3071                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3072                 }
3073 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3074                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3075                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3076                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3077                 {
3078                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3079                         if (rsurface.rtlight)
3080                         {
3081                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3082                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3083                         }
3084                 }
3085                 break;
3086         }
3087 }
3088
3089 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3090 {
3091         // select a permutation of the lighting shader appropriate to this
3092         // combination of texture, entity, light source, and fogging, only use the
3093         // minimum features necessary to avoid wasting rendering time in the
3094         // fragment shader on features that are not being used
3095         unsigned int permutation = 0;
3096         unsigned int mode = 0;
3097         const float *lightcolorbase = rtlight->currentcolor;
3098         float ambientscale = rtlight->ambientscale;
3099         float diffusescale = rtlight->diffusescale;
3100         float specularscale = rtlight->specularscale;
3101         // this is the location of the light in view space
3102         vec3_t viewlightorigin;
3103         // this transforms from view space (camera) to light space (cubemap)
3104         matrix4x4_t viewtolight;
3105         matrix4x4_t lighttoview;
3106         float viewtolight16f[16];
3107         // light source
3108         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3109         if (rtlight->currentcubemap != r_texture_whitecube)
3110                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3111         if (diffusescale > 0)
3112                 permutation |= SHADERPERMUTATION_DIFFUSE;
3113         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3114                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3115         if (r_shadow_usingshadowmap2d)
3116         {
3117                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3118                 if (r_shadow_shadowmapvsdct)
3119                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3120
3121                 if (r_shadow_shadowmap2ddepthbuffer)
3122                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3123         }
3124         if (vid.allowalphatocoverage)
3125                 GL_AlphaToCoverage(false);
3126         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3127         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3128         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3129         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3130         switch(vid.renderpath)
3131         {
3132         case RENDERPATH_D3D9:
3133 #ifdef SUPPORTD3D
3134                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3135                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3136                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3137                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3138                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3139                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3140                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3141                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3142                 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);
3143                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3144                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3145
3146                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3147                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3148                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3149                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3150                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3151 #endif
3152                 break;
3153         case RENDERPATH_D3D10:
3154                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3155                 break;
3156         case RENDERPATH_D3D11:
3157                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3158                 break;
3159         case RENDERPATH_GL20:
3160         case RENDERPATH_GLES2:
3161                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3162                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3163                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3164                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3165                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3166                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3167                 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]);
3168                 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]);
3169                 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);
3170                 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]);
3171                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3172
3173                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3174                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3175                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3176                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3177                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3178                 break;
3179         case RENDERPATH_GL11:
3180         case RENDERPATH_GL13:
3181         case RENDERPATH_GLES1:
3182                 break;
3183         case RENDERPATH_SOFT:
3184                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3185                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3186                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3187                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3188                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3189                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3190                 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]);
3191                 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]);
3192                 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);
3193                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3194                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3195
3196                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3197                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3198                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3199                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3200                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3201                 break;
3202         }
3203 }
3204
3205 #define SKINFRAME_HASH 1024
3206
3207 typedef struct
3208 {
3209         unsigned int loadsequence; // incremented each level change
3210         memexpandablearray_t array;
3211         skinframe_t *hash[SKINFRAME_HASH];
3212 }
3213 r_skinframe_t;
3214 r_skinframe_t r_skinframe;
3215
3216 void R_SkinFrame_PrepareForPurge(void)
3217 {
3218         r_skinframe.loadsequence++;
3219         // wrap it without hitting zero
3220         if (r_skinframe.loadsequence >= 200)
3221                 r_skinframe.loadsequence = 1;
3222 }
3223
3224 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3225 {
3226         if (!skinframe)
3227                 return;
3228         // mark the skinframe as used for the purging code
3229         skinframe->loadsequence = r_skinframe.loadsequence;
3230 }
3231
3232 void R_SkinFrame_Purge(void)
3233 {
3234         int i;
3235         skinframe_t *s;
3236         for (i = 0;i < SKINFRAME_HASH;i++)
3237         {
3238                 for (s = r_skinframe.hash[i];s;s = s->next)
3239                 {
3240                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3241                         {
3242                                 if (s->merged == s->base)
3243                                         s->merged = NULL;
3244                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3245                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3246                                 R_PurgeTexture(s->merged);s->merged = NULL;
3247                                 R_PurgeTexture(s->base  );s->base   = NULL;
3248                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3249                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3250                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3251                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3252                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3253                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3254                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3255                                 s->loadsequence = 0;
3256                         }
3257                 }
3258         }
3259 }
3260
3261 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3262         skinframe_t *item;
3263         char basename[MAX_QPATH];
3264
3265         Image_StripImageExtension(name, basename, sizeof(basename));
3266
3267         if( last == NULL ) {
3268                 int hashindex;
3269                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3270                 item = r_skinframe.hash[hashindex];
3271         } else {
3272                 item = last->next;
3273         }
3274
3275         // linearly search through the hash bucket
3276         for( ; item ; item = item->next ) {
3277                 if( !strcmp( item->basename, basename ) ) {
3278                         return item;
3279                 }
3280         }
3281         return NULL;
3282 }
3283
3284 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3285 {
3286         skinframe_t *item;
3287         int hashindex;
3288         char basename[MAX_QPATH];
3289
3290         Image_StripImageExtension(name, basename, sizeof(basename));
3291
3292         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3293         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3294                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3295                         break;
3296
3297         if (!item) {
3298                 rtexture_t *dyntexture;
3299                 // check whether its a dynamic texture
3300                 dyntexture = CL_GetDynTexture( basename );
3301                 if (!add && !dyntexture)
3302                         return NULL;
3303                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3304                 memset(item, 0, sizeof(*item));
3305                 strlcpy(item->basename, basename, sizeof(item->basename));
3306                 item->base = dyntexture; // either NULL or dyntexture handle
3307                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3308                 item->comparewidth = comparewidth;
3309                 item->compareheight = compareheight;
3310                 item->comparecrc = comparecrc;
3311                 item->next = r_skinframe.hash[hashindex];
3312                 r_skinframe.hash[hashindex] = item;
3313         }
3314         else if (textureflags & TEXF_FORCE_RELOAD)
3315         {
3316                 rtexture_t *dyntexture;
3317                 // check whether its a dynamic texture
3318                 dyntexture = CL_GetDynTexture( basename );
3319                 if (!add && !dyntexture)
3320                         return NULL;
3321                 if (item->merged == item->base)
3322                         item->merged = NULL;
3323                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3324                 R_PurgeTexture(item->stain );item->stain  = NULL;
3325                 R_PurgeTexture(item->merged);item->merged = NULL;
3326                 R_PurgeTexture(item->base  );item->base   = NULL;
3327                 R_PurgeTexture(item->pants );item->pants  = NULL;
3328                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3329                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3330                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3331                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3332                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3333         R_PurgeTexture(item->reflect);item->reflect = NULL;
3334                 item->loadsequence = 0;
3335         }
3336         else if( item->base == NULL )
3337         {
3338                 rtexture_t *dyntexture;
3339                 // check whether its a dynamic texture
3340                 // 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]
3341                 dyntexture = CL_GetDynTexture( basename );
3342                 item->base = dyntexture; // either NULL or dyntexture handle
3343         }
3344
3345         R_SkinFrame_MarkUsed(item);
3346         return item;
3347 }
3348
3349 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3350         { \
3351                 unsigned long long avgcolor[5], wsum; \
3352                 int pix, comp, w; \
3353                 avgcolor[0] = 0; \
3354                 avgcolor[1] = 0; \
3355                 avgcolor[2] = 0; \
3356                 avgcolor[3] = 0; \
3357                 avgcolor[4] = 0; \
3358                 wsum = 0; \
3359                 for(pix = 0; pix < cnt; ++pix) \
3360                 { \
3361                         w = 0; \
3362                         for(comp = 0; comp < 3; ++comp) \
3363                                 w += getpixel; \
3364                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3365                         { \
3366                                 ++wsum; \
3367                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3368                                 w = getpixel; \
3369                                 for(comp = 0; comp < 3; ++comp) \
3370                                         avgcolor[comp] += getpixel * w; \
3371                                 avgcolor[3] += w; \
3372                         } \
3373                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3374                         avgcolor[4] += getpixel; \
3375                 } \
3376                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3377                         avgcolor[3] = 1; \
3378                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3379                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3380                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3381                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3382         }
3383
3384 extern cvar_t gl_picmip;
3385 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3386 {
3387         int j;
3388         unsigned char *pixels;
3389         unsigned char *bumppixels;
3390         unsigned char *basepixels = NULL;
3391         int basepixels_width = 0;
3392         int basepixels_height = 0;
3393         skinframe_t *skinframe;
3394         rtexture_t *ddsbase = NULL;
3395         qboolean ddshasalpha = false;
3396         float ddsavgcolor[4];
3397         char basename[MAX_QPATH];
3398         int miplevel = R_PicmipForFlags(textureflags);
3399         int savemiplevel = miplevel;
3400         int mymiplevel;
3401         char vabuf[1024];
3402
3403         if (cls.state == ca_dedicated)
3404                 return NULL;
3405
3406         // return an existing skinframe if already loaded
3407         // if loading of the first image fails, don't make a new skinframe as it
3408         // would cause all future lookups of this to be missing
3409         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3410         if (skinframe && skinframe->base)
3411                 return skinframe;
3412
3413         Image_StripImageExtension(name, basename, sizeof(basename));
3414
3415         // check for DDS texture file first
3416         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3417         {
3418                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3419                 if (basepixels == NULL)
3420                         return NULL;
3421         }
3422
3423         // FIXME handle miplevel
3424
3425         if (developer_loading.integer)
3426                 Con_Printf("loading skin \"%s\"\n", name);
3427
3428         // we've got some pixels to store, so really allocate this new texture now
3429         if (!skinframe)
3430                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3431         textureflags &= ~TEXF_FORCE_RELOAD;
3432         skinframe->stain = NULL;
3433         skinframe->merged = NULL;
3434         skinframe->base = NULL;
3435         skinframe->pants = NULL;
3436         skinframe->shirt = NULL;
3437         skinframe->nmap = NULL;
3438         skinframe->gloss = NULL;
3439         skinframe->glow = NULL;
3440         skinframe->fog = NULL;
3441         skinframe->reflect = NULL;
3442         skinframe->hasalpha = false;
3443         // we could store the q2animname here too
3444
3445         if (ddsbase)
3446         {
3447                 skinframe->base = ddsbase;
3448                 skinframe->hasalpha = ddshasalpha;
3449                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3450                 if (r_loadfog && skinframe->hasalpha)
3451                         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);
3452                 //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]);
3453         }
3454         else
3455         {
3456                 basepixels_width = image_width;
3457                 basepixels_height = image_height;
3458                 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);
3459                 if (textureflags & TEXF_ALPHA)
3460                 {
3461                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3462                         {
3463                                 if (basepixels[j] < 255)
3464                                 {
3465                                         skinframe->hasalpha = true;
3466                                         break;
3467                                 }
3468                         }
3469                         if (r_loadfog && skinframe->hasalpha)
3470                         {
3471                                 // has transparent pixels
3472                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3473                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3474                                 {
3475                                         pixels[j+0] = 255;
3476                                         pixels[j+1] = 255;
3477                                         pixels[j+2] = 255;
3478                                         pixels[j+3] = basepixels[j+3];
3479                                 }
3480                                 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);
3481                                 Mem_Free(pixels);
3482                         }
3483                 }
3484                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3485 #ifndef USE_GLES2
3486                 //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]);
3487                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3488                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3489                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3490                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3491 #endif
3492         }
3493
3494         if (r_loaddds)
3495         {
3496                 mymiplevel = savemiplevel;
3497                 if (r_loadnormalmap)
3498                         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);
3499                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3500                 if (r_loadgloss)
3501                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3502                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3503                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3504                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3505         }
3506
3507         // _norm is the name used by tenebrae and has been adopted as standard
3508         if (r_loadnormalmap && skinframe->nmap == NULL)
3509         {
3510                 mymiplevel = savemiplevel;
3511                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3512                 {
3513                         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);
3514                         Mem_Free(pixels);
3515                         pixels = NULL;
3516                 }
3517                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3518                 {
3519                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3520                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3521                         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);
3522                         Mem_Free(pixels);
3523                         Mem_Free(bumppixels);
3524                 }
3525                 else if (r_shadow_bumpscale_basetexture.value > 0)
3526                 {
3527                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3528                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3529                         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);
3530                         Mem_Free(pixels);
3531                 }
3532 #ifndef USE_GLES2
3533                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3534                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3535 #endif
3536         }
3537
3538         // _luma is supported only for tenebrae compatibility
3539         // _glow is the preferred name
3540         mymiplevel = savemiplevel;
3541         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))))
3542         {
3543                 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);
3544 #ifndef USE_GLES2
3545                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3546                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3547 #endif
3548                 Mem_Free(pixels);pixels = NULL;
3549         }
3550
3551         mymiplevel = savemiplevel;
3552         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3553         {
3554                 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);
3555 #ifndef USE_GLES2
3556                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3557                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3558 #endif
3559                 Mem_Free(pixels);
3560                 pixels = NULL;
3561         }
3562
3563         mymiplevel = savemiplevel;
3564         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3565         {
3566                 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);
3567 #ifndef USE_GLES2
3568                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3569                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3570 #endif
3571                 Mem_Free(pixels);
3572                 pixels = NULL;
3573         }
3574
3575         mymiplevel = savemiplevel;
3576         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3577         {
3578                 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);
3579 #ifndef USE_GLES2
3580                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3581                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3582 #endif
3583                 Mem_Free(pixels);
3584                 pixels = NULL;
3585         }
3586
3587         mymiplevel = savemiplevel;
3588         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3589         {
3590                 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);
3591 #ifndef USE_GLES2
3592                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3593                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3594 #endif
3595                 Mem_Free(pixels);
3596                 pixels = NULL;
3597         }
3598
3599         if (basepixels)
3600                 Mem_Free(basepixels);
3601
3602         return skinframe;
3603 }
3604
3605 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3606 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3607 {
3608         int i;
3609         skinframe_t *skinframe;
3610         char vabuf[1024];
3611
3612         if (cls.state == ca_dedicated)
3613                 return NULL;
3614
3615         // if already loaded just return it, otherwise make a new skinframe
3616         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3617         if (skinframe->base)
3618                 return skinframe;
3619         textureflags &= ~TEXF_FORCE_RELOAD;
3620
3621         skinframe->stain = NULL;
3622         skinframe->merged = NULL;
3623         skinframe->base = NULL;
3624         skinframe->pants = NULL;
3625         skinframe->shirt = NULL;
3626         skinframe->nmap = NULL;
3627         skinframe->gloss = NULL;
3628         skinframe->glow = NULL;
3629         skinframe->fog = NULL;
3630         skinframe->reflect = NULL;
3631         skinframe->hasalpha = false;
3632
3633         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3634         if (!skindata)
3635                 return NULL;
3636
3637         if (developer_loading.integer)
3638                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3639
3640         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3641         {
3642                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3643                 unsigned char *b = a + width * height * 4;
3644                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3645                 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);
3646                 Mem_Free(a);
3647         }
3648         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3649         if (textureflags & TEXF_ALPHA)
3650         {
3651                 for (i = 3;i < width * height * 4;i += 4)
3652                 {
3653                         if (skindata[i] < 255)
3654                         {
3655                                 skinframe->hasalpha = true;
3656                                 break;
3657                         }
3658                 }
3659                 if (r_loadfog && skinframe->hasalpha)
3660                 {
3661                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3662                         memcpy(fogpixels, skindata, width * height * 4);
3663                         for (i = 0;i < width * height * 4;i += 4)
3664                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3665                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3666                         Mem_Free(fogpixels);
3667                 }
3668         }
3669
3670         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3671         //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]);
3672
3673         return skinframe;
3674 }
3675
3676 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3677 {
3678         int i;
3679         int featuresmask;
3680         skinframe_t *skinframe;
3681
3682         if (cls.state == ca_dedicated)
3683                 return NULL;
3684
3685         // if already loaded just return it, otherwise make a new skinframe
3686         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3687         if (skinframe->base)
3688                 return skinframe;
3689         //textureflags &= ~TEXF_FORCE_RELOAD;
3690
3691         skinframe->stain = NULL;
3692         skinframe->merged = NULL;
3693         skinframe->base = NULL;
3694         skinframe->pants = NULL;
3695         skinframe->shirt = NULL;
3696         skinframe->nmap = NULL;
3697         skinframe->gloss = NULL;
3698         skinframe->glow = NULL;
3699         skinframe->fog = NULL;
3700         skinframe->reflect = NULL;
3701         skinframe->hasalpha = false;
3702
3703         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3704         if (!skindata)
3705                 return NULL;
3706
3707         if (developer_loading.integer)
3708                 Con_Printf("loading quake skin \"%s\"\n", name);
3709
3710         // 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)
3711         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3712         memcpy(skinframe->qpixels, skindata, width*height);
3713         skinframe->qwidth = width;
3714         skinframe->qheight = height;
3715
3716         featuresmask = 0;
3717         for (i = 0;i < width * height;i++)
3718                 featuresmask |= palette_featureflags[skindata[i]];
3719
3720         skinframe->hasalpha = false;
3721         // fence textures
3722         if (name[0] == '{')
3723                 skinframe->hasalpha = true;
3724         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3725         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3726         skinframe->qgeneratemerged = true;
3727         skinframe->qgeneratebase = skinframe->qhascolormapping;
3728         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3729
3730         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3731         //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]);
3732
3733         return skinframe;
3734 }
3735
3736 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3737 {
3738         int width;
3739         int height;
3740         unsigned char *skindata;
3741         char vabuf[1024];
3742
3743         if (!skinframe->qpixels)
3744                 return;
3745
3746         if (!skinframe->qhascolormapping)
3747                 colormapped = false;
3748
3749         if (colormapped)
3750         {
3751                 if (!skinframe->qgeneratebase)
3752                         return;
3753         }
3754         else
3755         {
3756                 if (!skinframe->qgeneratemerged)
3757                         return;
3758         }
3759
3760         width = skinframe->qwidth;
3761         height = skinframe->qheight;
3762         skindata = skinframe->qpixels;
3763
3764         if (skinframe->qgeneratenmap)
3765         {
3766                 unsigned char *a, *b;
3767                 skinframe->qgeneratenmap = false;
3768                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3769                 b = a + width * height * 4;
3770                 // use either a custom palette or the quake palette
3771                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3772                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3773                 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);
3774                 Mem_Free(a);
3775         }
3776
3777         if (skinframe->qgenerateglow)
3778         {
3779                 skinframe->qgenerateglow = false;
3780                 if (skinframe->hasalpha) // fence textures
3781                         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
3782                 else
3783                         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
3784         }
3785
3786         if (colormapped)
3787         {
3788                 skinframe->qgeneratebase = false;
3789                 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);
3790                 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);
3791                 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);
3792         }
3793         else
3794         {
3795                 skinframe->qgeneratemerged = false;
3796                 if (skinframe->hasalpha) // fence textures
3797                         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);
3798                 else
3799                         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);
3800         }
3801
3802         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3803         {
3804                 Mem_Free(skinframe->qpixels);
3805                 skinframe->qpixels = NULL;
3806         }
3807 }
3808
3809 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)
3810 {
3811         int i;
3812         skinframe_t *skinframe;
3813         char vabuf[1024];
3814
3815         if (cls.state == ca_dedicated)
3816                 return NULL;
3817
3818         // if already loaded just return it, otherwise make a new skinframe
3819         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3820         if (skinframe->base)
3821                 return skinframe;
3822         textureflags &= ~TEXF_FORCE_RELOAD;
3823
3824         skinframe->stain = NULL;
3825         skinframe->merged = NULL;
3826         skinframe->base = NULL;
3827         skinframe->pants = NULL;
3828         skinframe->shirt = NULL;
3829         skinframe->nmap = NULL;
3830         skinframe->gloss = NULL;
3831         skinframe->glow = NULL;
3832         skinframe->fog = NULL;
3833         skinframe->reflect = NULL;
3834         skinframe->hasalpha = false;
3835
3836         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3837         if (!skindata)
3838                 return NULL;
3839
3840         if (developer_loading.integer)
3841                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3842
3843         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3844         if (textureflags & TEXF_ALPHA)
3845         {
3846                 for (i = 0;i < width * height;i++)
3847                 {
3848                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3849                         {
3850                                 skinframe->hasalpha = true;
3851                                 break;
3852                         }
3853                 }
3854                 if (r_loadfog && skinframe->hasalpha)
3855                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3856         }
3857
3858         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3859         //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]);
3860
3861         return skinframe;
3862 }
3863
3864 skinframe_t *R_SkinFrame_LoadMissing(void)
3865 {
3866         skinframe_t *skinframe;
3867
3868         if (cls.state == ca_dedicated)
3869                 return NULL;
3870
3871         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3872         skinframe->stain = NULL;
3873         skinframe->merged = NULL;
3874         skinframe->base = NULL;
3875         skinframe->pants = NULL;
3876         skinframe->shirt = NULL;
3877         skinframe->nmap = NULL;
3878         skinframe->gloss = NULL;
3879         skinframe->glow = NULL;
3880         skinframe->fog = NULL;
3881         skinframe->reflect = NULL;
3882         skinframe->hasalpha = false;
3883
3884         skinframe->avgcolor[0] = rand() / RAND_MAX;
3885         skinframe->avgcolor[1] = rand() / RAND_MAX;
3886         skinframe->avgcolor[2] = rand() / RAND_MAX;
3887         skinframe->avgcolor[3] = 1;
3888
3889         return skinframe;
3890 }
3891
3892 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3893 typedef struct suffixinfo_s
3894 {
3895         const char *suffix;
3896         qboolean flipx, flipy, flipdiagonal;
3897 }
3898 suffixinfo_t;
3899 static suffixinfo_t suffix[3][6] =
3900 {
3901         {
3902                 {"px",   false, false, false},
3903                 {"nx",   false, false, false},
3904                 {"py",   false, false, false},
3905                 {"ny",   false, false, false},
3906                 {"pz",   false, false, false},
3907                 {"nz",   false, false, false}
3908         },
3909         {
3910                 {"posx", false, false, false},
3911                 {"negx", false, false, false},
3912                 {"posy", false, false, false},
3913                 {"negy", false, false, false},
3914                 {"posz", false, false, false},
3915                 {"negz", false, false, false}
3916         },
3917         {
3918                 {"rt",    true, false,  true},
3919                 {"lf",   false,  true,  true},
3920                 {"ft",    true,  true, false},
3921                 {"bk",   false, false, false},
3922                 {"up",    true, false,  true},
3923                 {"dn",    true, false,  true}
3924         }
3925 };
3926
3927 static int componentorder[4] = {0, 1, 2, 3};
3928
3929 static rtexture_t *R_LoadCubemap(const char *basename)
3930 {
3931         int i, j, cubemapsize;
3932         unsigned char *cubemappixels, *image_buffer;
3933         rtexture_t *cubemaptexture;
3934         char name[256];
3935         // must start 0 so the first loadimagepixels has no requested width/height
3936         cubemapsize = 0;
3937         cubemappixels = NULL;
3938         cubemaptexture = NULL;
3939         // keep trying different suffix groups (posx, px, rt) until one loads
3940         for (j = 0;j < 3 && !cubemappixels;j++)
3941         {
3942                 // load the 6 images in the suffix group
3943                 for (i = 0;i < 6;i++)
3944                 {
3945                         // generate an image name based on the base and and suffix
3946                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3947                         // load it
3948                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3949                         {
3950                                 // an image loaded, make sure width and height are equal
3951                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3952                                 {
3953                                         // if this is the first image to load successfully, allocate the cubemap memory
3954                                         if (!cubemappixels && image_width >= 1)
3955                                         {
3956                                                 cubemapsize = image_width;
3957                                                 // note this clears to black, so unavailable sides are black
3958                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3959                                         }
3960                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3961                                         if (cubemappixels)
3962                                                 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);
3963                                 }
3964                                 else
3965                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3966                                 // free the image
3967                                 Mem_Free(image_buffer);
3968                         }
3969                 }
3970         }
3971         // if a cubemap loaded, upload it
3972         if (cubemappixels)
3973         {
3974                 if (developer_loading.integer)
3975                         Con_Printf("loading cubemap \"%s\"\n", basename);
3976
3977                 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);
3978                 Mem_Free(cubemappixels);
3979         }
3980         else
3981         {
3982                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3983                 if (developer_loading.integer)
3984                 {
3985                         Con_Printf("(tried tried images ");
3986                         for (j = 0;j < 3;j++)
3987                                 for (i = 0;i < 6;i++)
3988                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3989                         Con_Print(" and was unable to find any of them).\n");
3990                 }
3991         }
3992         return cubemaptexture;
3993 }
3994
3995 rtexture_t *R_GetCubemap(const char *basename)
3996 {
3997         int i;
3998         for (i = 0;i < r_texture_numcubemaps;i++)
3999                 if (r_texture_cubemaps[i] != NULL)
4000                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4001                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4002         if (i >= MAX_CUBEMAPS || !r_main_mempool)
4003                 return r_texture_whitecube;
4004         r_texture_numcubemaps++;
4005         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4006         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4007         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4008         return r_texture_cubemaps[i]->texture;
4009 }
4010
4011 static void R_Main_FreeViewCache(void)
4012 {
4013         if (r_refdef.viewcache.entityvisible)
4014                 Mem_Free(r_refdef.viewcache.entityvisible);
4015         if (r_refdef.viewcache.world_pvsbits)
4016                 Mem_Free(r_refdef.viewcache.world_pvsbits);
4017         if (r_refdef.viewcache.world_leafvisible)
4018                 Mem_Free(r_refdef.viewcache.world_leafvisible);
4019         if (r_refdef.viewcache.world_surfacevisible)
4020                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4021         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4022 }
4023
4024 static void R_Main_ResizeViewCache(void)
4025 {
4026         int numentities = r_refdef.scene.numentities;
4027         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4028         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4029         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4030         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4031         if (r_refdef.viewcache.maxentities < numentities)
4032         {
4033                 r_refdef.viewcache.maxentities = numentities;
4034                 if (r_refdef.viewcache.entityvisible)
4035                         Mem_Free(r_refdef.viewcache.entityvisible);
4036                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4037         }
4038         if (r_refdef.viewcache.world_numclusters != numclusters)
4039         {
4040                 r_refdef.viewcache.world_numclusters = numclusters;
4041                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4042                 if (r_refdef.viewcache.world_pvsbits)
4043                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4044                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4045         }
4046         if (r_refdef.viewcache.world_numleafs != numleafs)
4047         {
4048                 r_refdef.viewcache.world_numleafs = numleafs;
4049                 if (r_refdef.viewcache.world_leafvisible)
4050                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4051                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4052         }
4053         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4054         {
4055                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4056                 if (r_refdef.viewcache.world_surfacevisible)
4057                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4058                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4059         }
4060 }
4061
4062 extern rtexture_t *loadingscreentexture;
4063 static void gl_main_start(void)
4064 {
4065         loadingscreentexture = NULL;
4066         r_texture_blanknormalmap = NULL;
4067         r_texture_white = NULL;
4068         r_texture_grey128 = NULL;
4069         r_texture_black = NULL;
4070         r_texture_whitecube = NULL;
4071         r_texture_normalizationcube = NULL;
4072         r_texture_fogattenuation = NULL;
4073         r_texture_fogheighttexture = NULL;
4074         r_texture_gammaramps = NULL;
4075         r_texture_numcubemaps = 0;
4076         r_uniformbufferalignment = 32;
4077
4078         r_loaddds = r_texture_dds_load.integer != 0;
4079         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4080
4081         switch(vid.renderpath)
4082         {
4083         case RENDERPATH_GL20:
4084         case RENDERPATH_D3D9:
4085         case RENDERPATH_D3D10:
4086         case RENDERPATH_D3D11:
4087         case RENDERPATH_SOFT:
4088         case RENDERPATH_GLES2:
4089                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4090                 Cvar_SetValueQuick(&gl_combine, 1);
4091                 Cvar_SetValueQuick(&r_glsl, 1);
4092                 r_loadnormalmap = true;
4093                 r_loadgloss = true;
4094                 r_loadfog = false;
4095 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4096                 if (vid.support.arb_uniform_buffer_object)
4097                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4098 #endif
4099                         break;
4100         case RENDERPATH_GL13:
4101         case RENDERPATH_GLES1:
4102                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4103                 Cvar_SetValueQuick(&gl_combine, 1);
4104                 Cvar_SetValueQuick(&r_glsl, 0);
4105                 r_loadnormalmap = false;
4106                 r_loadgloss = false;
4107                 r_loadfog = true;
4108                 break;
4109         case RENDERPATH_GL11:
4110                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4111                 Cvar_SetValueQuick(&gl_combine, 0);
4112                 Cvar_SetValueQuick(&r_glsl, 0);
4113                 r_loadnormalmap = false;
4114                 r_loadgloss = false;
4115                 r_loadfog = true;
4116                 break;
4117         }
4118
4119         R_AnimCache_Free();
4120         R_FrameData_Reset();
4121         R_BufferData_Reset();
4122
4123         r_numqueries = 0;
4124         r_maxqueries = 0;
4125         memset(r_queries, 0, sizeof(r_queries));
4126
4127         r_qwskincache = NULL;
4128         r_qwskincache_size = 0;
4129
4130         // due to caching of texture_t references, the collision cache must be reset
4131         Collision_Cache_Reset(true);
4132
4133         // set up r_skinframe loading system for textures
4134         memset(&r_skinframe, 0, sizeof(r_skinframe));
4135         r_skinframe.loadsequence = 1;
4136         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4137
4138         r_main_texturepool = R_AllocTexturePool();
4139         R_BuildBlankTextures();
4140         R_BuildNoTexture();
4141         if (vid.support.arb_texture_cube_map)
4142         {
4143                 R_BuildWhiteCube();
4144                 R_BuildNormalizationCube();
4145         }
4146         r_texture_fogattenuation = NULL;
4147         r_texture_fogheighttexture = NULL;
4148         r_texture_gammaramps = NULL;
4149         //r_texture_fogintensity = NULL;
4150         memset(&r_fb, 0, sizeof(r_fb));
4151         r_glsl_permutation = NULL;
4152         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4153         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4154         glslshaderstring = NULL;
4155 #ifdef SUPPORTD3D
4156         r_hlsl_permutation = NULL;
4157         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4158         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4159 #endif
4160         hlslshaderstring = NULL;
4161         memset(&r_svbsp, 0, sizeof (r_svbsp));
4162
4163         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4164         r_texture_numcubemaps = 0;
4165
4166         r_refdef.fogmasktable_density = 0;
4167
4168 #ifdef __ANDROID__
4169         // For Steelstorm Android
4170         // FIXME CACHE the program and reload
4171         // FIXME see possible combinations for SS:BR android
4172         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4173         R_SetupShader_SetPermutationGLSL(0, 12);
4174         R_SetupShader_SetPermutationGLSL(0, 13);
4175         R_SetupShader_SetPermutationGLSL(0, 8388621);
4176         R_SetupShader_SetPermutationGLSL(3, 0);
4177         R_SetupShader_SetPermutationGLSL(3, 2048);
4178         R_SetupShader_SetPermutationGLSL(5, 0);
4179         R_SetupShader_SetPermutationGLSL(5, 2);
4180         R_SetupShader_SetPermutationGLSL(5, 2048);
4181         R_SetupShader_SetPermutationGLSL(5, 8388608);
4182         R_SetupShader_SetPermutationGLSL(11, 1);
4183         R_SetupShader_SetPermutationGLSL(11, 2049);
4184         R_SetupShader_SetPermutationGLSL(11, 8193);
4185         R_SetupShader_SetPermutationGLSL(11, 10241);
4186         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4187 #endif
4188 }
4189
4190 static void gl_main_shutdown(void)
4191 {
4192         R_AnimCache_Free();
4193         R_FrameData_Reset();
4194         R_BufferData_Reset();
4195
4196         R_Main_FreeViewCache();
4197
4198         switch(vid.renderpath)
4199         {
4200         case RENDERPATH_GL11:
4201         case RENDERPATH_GL13:
4202         case RENDERPATH_GL20:
4203         case RENDERPATH_GLES1:
4204         case RENDERPATH_GLES2:
4205 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4206                 if (r_maxqueries)
4207                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4208 #endif
4209                 break;
4210         case RENDERPATH_D3D9:
4211                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4212                 break;
4213         case RENDERPATH_D3D10:
4214                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4215                 break;
4216         case RENDERPATH_D3D11:
4217                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4218                 break;
4219         case RENDERPATH_SOFT:
4220                 break;
4221         }
4222
4223         r_numqueries = 0;
4224         r_maxqueries = 0;
4225         memset(r_queries, 0, sizeof(r_queries));
4226
4227         r_qwskincache = NULL;
4228         r_qwskincache_size = 0;
4229
4230         // clear out the r_skinframe state
4231         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4232         memset(&r_skinframe, 0, sizeof(r_skinframe));
4233
4234         if (r_svbsp.nodes)
4235                 Mem_Free(r_svbsp.nodes);
4236         memset(&r_svbsp, 0, sizeof (r_svbsp));
4237         R_FreeTexturePool(&r_main_texturepool);
4238         loadingscreentexture = NULL;
4239         r_texture_blanknormalmap = NULL;
4240         r_texture_white = NULL;
4241         r_texture_grey128 = NULL;
4242         r_texture_black = NULL;
4243         r_texture_whitecube = NULL;
4244         r_texture_normalizationcube = NULL;
4245         r_texture_fogattenuation = NULL;
4246         r_texture_fogheighttexture = NULL;
4247         r_texture_gammaramps = NULL;
4248         r_texture_numcubemaps = 0;
4249         //r_texture_fogintensity = NULL;
4250         memset(&r_fb, 0, sizeof(r_fb));
4251         R_GLSL_Restart_f();
4252
4253         r_glsl_permutation = NULL;
4254         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4255         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4256         glslshaderstring = NULL;
4257 #ifdef SUPPORTD3D
4258         r_hlsl_permutation = NULL;
4259         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4260         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4261 #endif
4262         hlslshaderstring = NULL;
4263 }
4264
4265 static void gl_main_newmap(void)
4266 {
4267         // FIXME: move this code to client
4268         char *entities, entname[MAX_QPATH];
4269         if (r_qwskincache)
4270                 Mem_Free(r_qwskincache);
4271         r_qwskincache = NULL;
4272         r_qwskincache_size = 0;
4273         if (cl.worldmodel)
4274         {
4275                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4276                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4277                 {
4278                         CL_ParseEntityLump(entities);
4279                         Mem_Free(entities);
4280                         return;
4281                 }
4282                 if (cl.worldmodel->brush.entities)
4283                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4284         }
4285         R_Main_FreeViewCache();
4286
4287         R_FrameData_Reset();
4288         R_BufferData_Reset();
4289 }
4290
4291 void GL_Main_Init(void)
4292 {
4293         int i;
4294         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4295
4296         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4297         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4298         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4299         if (gamemode == GAME_NEHAHRA)
4300         {
4301                 Cvar_RegisterVariable (&gl_fogenable);
4302                 Cvar_RegisterVariable (&gl_fogdensity);
4303                 Cvar_RegisterVariable (&gl_fogred);
4304                 Cvar_RegisterVariable (&gl_foggreen);
4305                 Cvar_RegisterVariable (&gl_fogblue);
4306                 Cvar_RegisterVariable (&gl_fogstart);
4307                 Cvar_RegisterVariable (&gl_fogend);
4308                 Cvar_RegisterVariable (&gl_skyclip);
4309         }
4310         Cvar_RegisterVariable(&r_motionblur);
4311         Cvar_RegisterVariable(&r_damageblur);
4312         Cvar_RegisterVariable(&r_motionblur_averaging);
4313         Cvar_RegisterVariable(&r_motionblur_randomize);
4314         Cvar_RegisterVariable(&r_motionblur_minblur);
4315         Cvar_RegisterVariable(&r_motionblur_maxblur);
4316         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4317         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4318         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4319         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4320         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4321         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4322         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4323         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4324         Cvar_RegisterVariable(&r_equalize_entities_by);
4325         Cvar_RegisterVariable(&r_equalize_entities_to);
4326         Cvar_RegisterVariable(&r_depthfirst);
4327         Cvar_RegisterVariable(&r_useinfinitefarclip);
4328         Cvar_RegisterVariable(&r_farclip_base);
4329         Cvar_RegisterVariable(&r_farclip_world);
4330         Cvar_RegisterVariable(&r_nearclip);
4331         Cvar_RegisterVariable(&r_deformvertexes);
4332         Cvar_RegisterVariable(&r_transparent);
4333         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4334         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4335         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4336         Cvar_RegisterVariable(&r_showoverdraw);
4337         Cvar_RegisterVariable(&r_showbboxes);
4338         Cvar_RegisterVariable(&r_showsurfaces);
4339         Cvar_RegisterVariable(&r_showtris);
4340         Cvar_RegisterVariable(&r_shownormals);
4341         Cvar_RegisterVariable(&r_showlighting);
4342         Cvar_RegisterVariable(&r_showshadowvolumes);
4343         Cvar_RegisterVariable(&r_showcollisionbrushes);
4344         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4345         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4346         Cvar_RegisterVariable(&r_showdisabledepthtest);
4347         Cvar_RegisterVariable(&r_drawportals);
4348         Cvar_RegisterVariable(&r_drawentities);
4349         Cvar_RegisterVariable(&r_draw2d);
4350         Cvar_RegisterVariable(&r_drawworld);
4351         Cvar_RegisterVariable(&r_cullentities_trace);
4352         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4353         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4354         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4355         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4356         Cvar_RegisterVariable(&r_sortentities);
4357         Cvar_RegisterVariable(&r_drawviewmodel);
4358         Cvar_RegisterVariable(&r_drawexteriormodel);
4359         Cvar_RegisterVariable(&r_speeds);
4360         Cvar_RegisterVariable(&r_fullbrights);
4361         Cvar_RegisterVariable(&r_wateralpha);
4362         Cvar_RegisterVariable(&r_dynamic);
4363         Cvar_RegisterVariable(&r_fakelight);
4364         Cvar_RegisterVariable(&r_fakelight_intensity);
4365         Cvar_RegisterVariable(&r_fullbright);
4366         Cvar_RegisterVariable(&r_shadows);
4367         Cvar_RegisterVariable(&r_shadows_darken);
4368         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4369         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4370         Cvar_RegisterVariable(&r_shadows_throwdistance);
4371         Cvar_RegisterVariable(&r_shadows_throwdirection);
4372         Cvar_RegisterVariable(&r_shadows_focus);
4373         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4374         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4375         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4376         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4377         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4378         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4379         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4380         Cvar_RegisterVariable(&r_fog_exp2);
4381         Cvar_RegisterVariable(&r_fog_clear);
4382         Cvar_RegisterVariable(&r_drawfog);
4383         Cvar_RegisterVariable(&r_transparentdepthmasking);
4384         Cvar_RegisterVariable(&r_transparent_sortmindist);
4385         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4386         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4387         Cvar_RegisterVariable(&r_texture_dds_load);
4388         Cvar_RegisterVariable(&r_texture_dds_save);
4389         Cvar_RegisterVariable(&r_textureunits);
4390         Cvar_RegisterVariable(&gl_combine);
4391         Cvar_RegisterVariable(&r_usedepthtextures);
4392         Cvar_RegisterVariable(&r_viewfbo);
4393         Cvar_RegisterVariable(&r_viewscale);
4394         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4395         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4396         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4397         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4398         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4399         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4400         Cvar_RegisterVariable(&r_glsl);
4401         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4402         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4403         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4404         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4405         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4406         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4407         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4408         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4409         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4410         Cvar_RegisterVariable(&r_glsl_postprocess);
4411         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4412         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4413         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4414         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4415         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4416         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4417         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4418         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4419         Cvar_RegisterVariable(&r_celshading);
4420         Cvar_RegisterVariable(&r_celoutlines);
4421
4422         Cvar_RegisterVariable(&r_water);
4423         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4424         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4425         Cvar_RegisterVariable(&r_water_clippingplanebias);
4426         Cvar_RegisterVariable(&r_water_refractdistort);
4427         Cvar_RegisterVariable(&r_water_reflectdistort);
4428         Cvar_RegisterVariable(&r_water_scissormode);
4429         Cvar_RegisterVariable(&r_water_lowquality);
4430         Cvar_RegisterVariable(&r_water_hideplayer);
4431         Cvar_RegisterVariable(&r_water_fbo);
4432
4433         Cvar_RegisterVariable(&r_lerpsprites);
4434         Cvar_RegisterVariable(&r_lerpmodels);
4435         Cvar_RegisterVariable(&r_lerplightstyles);
4436         Cvar_RegisterVariable(&r_waterscroll);
4437         Cvar_RegisterVariable(&r_bloom);
4438         Cvar_RegisterVariable(&r_bloom_colorscale);
4439         Cvar_RegisterVariable(&r_bloom_brighten);
4440         Cvar_RegisterVariable(&r_bloom_blur);
4441         Cvar_RegisterVariable(&r_bloom_resolution);
4442         Cvar_RegisterVariable(&r_bloom_colorexponent);
4443         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4444         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4445         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4446         Cvar_RegisterVariable(&r_hdr_glowintensity);
4447         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4448         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4449         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4450         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4451         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4452         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4453         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4454         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4455         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4456         Cvar_RegisterVariable(&developer_texturelogging);
4457         Cvar_RegisterVariable(&gl_lightmaps);
4458         Cvar_RegisterVariable(&r_test);
4459         Cvar_RegisterVariable(&r_batch_multidraw);
4460         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4461         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4462         Cvar_RegisterVariable(&r_glsl_skeletal);
4463         Cvar_RegisterVariable(&r_glsl_saturation);
4464         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4465         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4466         Cvar_RegisterVariable(&r_framedatasize);
4467         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4468                 Cvar_RegisterVariable(&r_buffermegs[i]);
4469         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4470         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4471                 Cvar_SetValue("r_fullbrights", 0);
4472 #ifdef DP_MOBILETOUCH
4473         // GLES devices have terrible depth precision in general, so...
4474         Cvar_SetValueQuick(&r_nearclip, 4);
4475         Cvar_SetValueQuick(&r_farclip_base, 4096);
4476         Cvar_SetValueQuick(&r_farclip_world, 0);
4477         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4478 #endif
4479         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4480 }
4481
4482 void Render_Init(void)
4483 {
4484         gl_backend_init();
4485         R_Textures_Init();
4486         GL_Main_Init();
4487         Font_Init();
4488         GL_Draw_Init();
4489         R_Shadow_Init();
4490         R_Sky_Init();
4491         GL_Surf_Init();
4492         Sbar_Init();
4493         R_Particles_Init();
4494         R_Explosion_Init();
4495         R_LightningBeams_Init();
4496         Mod_RenderInit();
4497 }
4498
4499 /*
4500 ===============
4501 GL_Init
4502 ===============
4503 */
4504 #ifndef USE_GLES2
4505 extern char *ENGINE_EXTENSIONS;
4506 void GL_Init (void)
4507 {
4508         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4509         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4510         gl_version = (const char *)qglGetString(GL_VERSION);
4511         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4512
4513         if (!gl_extensions)
4514                 gl_extensions = "";
4515         if (!gl_platformextensions)
4516                 gl_platformextensions = "";
4517
4518         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4519         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4520         Con_Printf("GL_VERSION: %s\n", gl_version);
4521         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4522         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4523
4524         VID_CheckExtensions();
4525
4526         // LordHavoc: report supported extensions
4527 #ifdef CONFIG_MENU
4528         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4529 #else
4530         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4531 #endif
4532
4533         // clear to black (loading plaque will be seen over this)
4534         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4535 }
4536 #endif
4537
4538 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4539 {
4540         int i;
4541         mplane_t *p;
4542         if (r_trippy.integer)
4543                 return false;
4544         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4545         {
4546                 p = r_refdef.view.frustum + i;
4547                 switch(p->signbits)
4548                 {
4549                 default:
4550                 case 0:
4551                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4552                                 return true;
4553                         break;
4554                 case 1:
4555                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4556                                 return true;
4557                         break;
4558                 case 2:
4559                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4560                                 return true;
4561                         break;
4562                 case 3:
4563                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4564                                 return true;
4565                         break;
4566                 case 4:
4567                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4568                                 return true;
4569                         break;
4570                 case 5:
4571                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4572                                 return true;
4573                         break;
4574                 case 6:
4575                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4576                                 return true;
4577                         break;
4578                 case 7:
4579                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4580                                 return true;
4581                         break;
4582                 }
4583         }
4584         return false;
4585 }
4586
4587 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4588 {
4589         int i;
4590         const mplane_t *p;
4591         if (r_trippy.integer)
4592                 return false;
4593         for (i = 0;i < numplanes;i++)
4594         {
4595                 p = planes + i;
4596                 switch(p->signbits)
4597                 {
4598                 default:
4599                 case 0:
4600                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4601                                 return true;
4602                         break;
4603                 case 1:
4604                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4605                                 return true;
4606                         break;
4607                 case 2:
4608                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4609                                 return true;
4610                         break;
4611                 case 3:
4612                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4613                                 return true;
4614                         break;
4615                 case 4:
4616                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4617                                 return true;
4618                         break;
4619                 case 5:
4620                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4621                                 return true;
4622                         break;
4623                 case 6:
4624                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4625                                 return true;
4626                         break;
4627                 case 7:
4628                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4629                                 return true;
4630                         break;
4631                 }
4632         }
4633         return false;
4634 }
4635
4636 //==================================================================================
4637
4638 // LordHavoc: this stores temporary data used within the same frame
4639
4640 typedef struct r_framedata_mem_s
4641 {
4642         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4643         size_t size; // how much usable space
4644         size_t current; // how much space in use
4645         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4646         size_t wantedsize; // how much space was allocated
4647         unsigned char *data; // start of real data (16byte aligned)
4648 }
4649 r_framedata_mem_t;
4650
4651 static r_framedata_mem_t *r_framedata_mem;
4652
4653 void R_FrameData_Reset(void)
4654 {
4655         while (r_framedata_mem)
4656         {
4657                 r_framedata_mem_t *next = r_framedata_mem->purge;
4658                 Mem_Free(r_framedata_mem);
4659                 r_framedata_mem = next;
4660         }
4661 }
4662
4663 static void R_FrameData_Resize(qboolean mustgrow)
4664 {
4665         size_t wantedsize;
4666         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4667         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4668         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4669         {
4670                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4671                 newmem->wantedsize = wantedsize;
4672                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4673                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4674                 newmem->current = 0;
4675                 newmem->mark = 0;
4676                 newmem->purge = r_framedata_mem;
4677                 r_framedata_mem = newmem;
4678         }
4679 }
4680
4681 void R_FrameData_NewFrame(void)
4682 {
4683         R_FrameData_Resize(false);
4684         if (!r_framedata_mem)
4685                 return;
4686         // if we ran out of space on the last frame, free the old memory now
4687         while (r_framedata_mem->purge)
4688         {
4689                 // repeatedly remove the second item in the list, leaving only head
4690                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4691                 Mem_Free(r_framedata_mem->purge);
4692                 r_framedata_mem->purge = next;
4693         }
4694         // reset the current mem pointer
4695         r_framedata_mem->current = 0;
4696         r_framedata_mem->mark = 0;
4697 }
4698
4699 void *R_FrameData_Alloc(size_t size)
4700 {
4701         void *data;
4702         float newvalue;
4703
4704         // align to 16 byte boundary - the data pointer is already aligned, so we
4705         // only need to ensure the size of every allocation is also aligned
4706         size = (size + 15) & ~15;
4707
4708         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4709         {
4710                 // emergency - we ran out of space, allocate more memory
4711                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4712                 // this might not be a growing it, but we'll allocate another buffer every time
4713                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4714                 R_FrameData_Resize(true);
4715         }
4716
4717         data = r_framedata_mem->data + r_framedata_mem->current;
4718         r_framedata_mem->current += size;
4719
4720         // count the usage for stats
4721         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4722         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4723
4724         return (void *)data;
4725 }
4726
4727 void *R_FrameData_Store(size_t size, void *data)
4728 {
4729         void *d = R_FrameData_Alloc(size);
4730         if (d && data)
4731                 memcpy(d, data, size);
4732         return d;
4733 }
4734
4735 void R_FrameData_SetMark(void)
4736 {
4737         if (!r_framedata_mem)
4738                 return;
4739         r_framedata_mem->mark = r_framedata_mem->current;
4740 }
4741
4742 void R_FrameData_ReturnToMark(void)
4743 {
4744         if (!r_framedata_mem)
4745                 return;
4746         r_framedata_mem->current = r_framedata_mem->mark;
4747 }
4748
4749 //==================================================================================
4750
4751 // avoid reusing the same buffer objects on consecutive frames
4752 #define R_BUFFERDATA_CYCLE 3
4753
4754 typedef struct r_bufferdata_buffer_s
4755 {
4756         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4757         size_t size; // how much usable space
4758         size_t current; // how much space in use
4759         r_meshbuffer_t *buffer; // the buffer itself
4760 }
4761 r_bufferdata_buffer_t;
4762
4763 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4764 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4765
4766 /// frees all dynamic buffers
4767 void R_BufferData_Reset(void)
4768 {
4769         int cycle, type;
4770         r_bufferdata_buffer_t **p, *mem;
4771         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4772         {
4773                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4774                 {
4775                         // free all buffers
4776                         p = &r_bufferdata_buffer[cycle][type];
4777                         while (*p)
4778                         {
4779                                 mem = *p;
4780                                 *p = (*p)->purge;
4781                                 if (mem->buffer)
4782                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4783                                 Mem_Free(mem);
4784                         }
4785                 }
4786         }
4787 }
4788
4789 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4790 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4791 {
4792         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4793         size_t size;
4794         float newvalue = r_buffermegs[type].value;
4795
4796         // increase the cvar if we have to (but only if we already have a mem)
4797         if (mustgrow && mem)
4798                 newvalue *= 2.0f;
4799         newvalue = bound(0.25f, newvalue, 256.0f);
4800         while (newvalue * 1024*1024 < minsize)
4801                 newvalue *= 2.0f;
4802
4803         // clamp the cvar to valid range
4804         newvalue = bound(0.25f, newvalue, 256.0f);
4805         if (r_buffermegs[type].value != newvalue)
4806                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4807
4808         // calculate size in bytes
4809         size = (size_t)(newvalue * 1024*1024);
4810         size = bound(131072, size, 256*1024*1024);
4811
4812         // allocate a new buffer if the size is different (purge old one later)
4813         // or if we were told we must grow the buffer
4814         if (!mem || mem->size != size || mustgrow)
4815         {
4816                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4817                 mem->size = size;
4818                 mem->current = 0;
4819                 if (type == R_BUFFERDATA_VERTEX)
4820                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4821                 else if (type == R_BUFFERDATA_INDEX16)
4822                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4823                 else if (type == R_BUFFERDATA_INDEX32)
4824                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4825                 else if (type == R_BUFFERDATA_UNIFORM)
4826                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4827                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4828                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4829         }
4830 }
4831
4832 void R_BufferData_NewFrame(void)
4833 {
4834         int type;
4835         r_bufferdata_buffer_t **p, *mem;
4836         // cycle to the next frame's buffers
4837         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4838         // if we ran out of space on the last time we used these buffers, free the old memory now
4839         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4840         {
4841                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4842                 {
4843                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4844                         // free all but the head buffer, this is how we recycle obsolete
4845                         // buffers after they are no longer in use
4846                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4847                         while (*p)
4848                         {
4849                                 mem = *p;
4850                                 *p = (*p)->purge;
4851                                 if (mem->buffer)
4852                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4853                                 Mem_Free(mem);
4854                         }
4855                         // reset the current offset
4856                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4857                 }
4858         }
4859 }
4860
4861 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4862 {
4863         r_bufferdata_buffer_t *mem;
4864         int offset = 0;
4865         int padsize;
4866
4867         *returnbufferoffset = 0;
4868
4869         // align size to a byte boundary appropriate for the buffer type, this
4870         // makes all allocations have aligned start offsets
4871         if (type == R_BUFFERDATA_UNIFORM)
4872                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4873         else
4874                 padsize = (datasize + 15) & ~15;
4875
4876         // if we ran out of space in this buffer we must allocate a new one
4877         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)
4878                 R_BufferData_Resize(type, true, padsize);
4879
4880         // if the resize did not give us enough memory, fail
4881         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)
4882                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4883
4884         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4885         offset = (int)mem->current;
4886         mem->current += padsize;
4887
4888         // upload the data to the buffer at the chosen offset
4889         if (offset == 0)
4890                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4891         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4892
4893         // count the usage for stats
4894         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4895         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4896
4897         // return the buffer offset
4898         *returnbufferoffset = offset;
4899
4900         return mem->buffer;
4901 }
4902
4903 //==================================================================================
4904
4905 // LordHavoc: animcache originally written by Echon, rewritten since then
4906
4907 /**
4908  * Animation cache prevents re-generating mesh data for an animated model
4909  * multiple times in one frame for lighting, shadowing, reflections, etc.
4910  */
4911
4912 void R_AnimCache_Free(void)
4913 {
4914 }
4915
4916 void R_AnimCache_ClearCache(void)
4917 {
4918         int i;
4919         entity_render_t *ent;
4920
4921         for (i = 0;i < r_refdef.scene.numentities;i++)
4922         {
4923                 ent = r_refdef.scene.entities[i];
4924                 ent->animcache_vertex3f = NULL;
4925                 ent->animcache_vertex3f_vertexbuffer = NULL;
4926                 ent->animcache_vertex3f_bufferoffset = 0;
4927                 ent->animcache_normal3f = NULL;
4928                 ent->animcache_normal3f_vertexbuffer = NULL;
4929                 ent->animcache_normal3f_bufferoffset = 0;
4930                 ent->animcache_svector3f = NULL;
4931                 ent->animcache_svector3f_vertexbuffer = NULL;
4932                 ent->animcache_svector3f_bufferoffset = 0;
4933                 ent->animcache_tvector3f = NULL;
4934                 ent->animcache_tvector3f_vertexbuffer = NULL;
4935                 ent->animcache_tvector3f_bufferoffset = 0;
4936                 ent->animcache_vertexmesh = NULL;
4937                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4938                 ent->animcache_vertexmesh_bufferoffset = 0;
4939                 ent->animcache_skeletaltransform3x4 = NULL;
4940                 ent->animcache_skeletaltransform3x4buffer = NULL;
4941                 ent->animcache_skeletaltransform3x4offset = 0;
4942                 ent->animcache_skeletaltransform3x4size = 0;
4943         }
4944 }
4945
4946 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4947 {
4948         int i;
4949
4950         // check if we need the meshbuffers
4951         if (!vid.useinterleavedarrays)
4952                 return;
4953
4954         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4955                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4956         // TODO: upload vertexbuffer?
4957         if (ent->animcache_vertexmesh)
4958         {
4959                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4960                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4961                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4962                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4963                 for (i = 0;i < numvertices;i++)
4964                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4965                 if (ent->animcache_svector3f)
4966                         for (i = 0;i < numvertices;i++)
4967                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4968                 if (ent->animcache_tvector3f)
4969                         for (i = 0;i < numvertices;i++)
4970                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4971                 if (ent->animcache_normal3f)
4972                         for (i = 0;i < numvertices;i++)
4973                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4974         }
4975 }
4976
4977 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4978 {
4979         dp_model_t *model = ent->model;
4980         int numvertices;
4981
4982         // see if this ent is worth caching
4983         if (!model || !model->Draw || !model->AnimateVertices)
4984                 return false;
4985         // nothing to cache if it contains no animations and has no skeleton
4986         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4987                 return false;
4988         // see if it is already cached for gpuskeletal
4989         if (ent->animcache_skeletaltransform3x4)
4990                 return false;
4991         // see if it is already cached as a mesh
4992         if (ent->animcache_vertex3f)
4993         {
4994                 // check if we need to add normals or tangents
4995                 if (ent->animcache_normal3f)
4996                         wantnormals = false;
4997                 if (ent->animcache_svector3f)
4998                         wanttangents = false;
4999                 if (!wantnormals && !wanttangents)
5000                         return false;
5001         }
5002
5003         // check which kind of cache we need to generate
5004         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5005         {
5006                 // cache the skeleton so the vertex shader can use it
5007                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5008                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5009                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5010                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5011                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
5012                 // note: this can fail if the buffer is at the grow limit
5013                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5014                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5015         }
5016         else if (ent->animcache_vertex3f)
5017         {
5018                 // mesh was already cached but we may need to add normals/tangents
5019                 // (this only happens with multiple views, reflections, cameras, etc)
5020                 if (wantnormals || wanttangents)
5021                 {
5022                         numvertices = model->surfmesh.num_vertices;
5023                         if (wantnormals)
5024                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5025                         if (wanttangents)
5026                         {
5027                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5028                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5029                         }
5030                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5031                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5032                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5033                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5034                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5035                 }
5036         }
5037         else
5038         {
5039                 // generate mesh cache
5040                 numvertices = model->surfmesh.num_vertices;
5041                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5042                 if (wantnormals)
5043                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5044                 if (wanttangents)
5045                 {
5046                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5047                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5048                 }
5049                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5050                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5051                 if (wantnormals || wanttangents)
5052                 {
5053                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5054                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5055                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5056                 }
5057                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5058                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5059                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5060         }
5061         return true;
5062 }
5063
5064 void R_AnimCache_CacheVisibleEntities(void)
5065 {
5066         int i;
5067         qboolean wantnormals = true;
5068         qboolean wanttangents = !r_showsurfaces.integer;
5069
5070         switch(vid.renderpath)
5071         {
5072         case RENDERPATH_GL20:
5073         case RENDERPATH_D3D9:
5074         case RENDERPATH_D3D10:
5075         case RENDERPATH_D3D11:
5076         case RENDERPATH_GLES2:
5077                 break;
5078         case RENDERPATH_GL11:
5079         case RENDERPATH_GL13:
5080         case RENDERPATH_GLES1:
5081                 wanttangents = false;
5082                 break;
5083         case RENDERPATH_SOFT:
5084                 break;
5085         }
5086
5087         if (r_shownormals.integer)
5088                 wanttangents = wantnormals = true;
5089
5090         // TODO: thread this
5091         // NOTE: R_PrepareRTLights() also caches entities
5092
5093         for (i = 0;i < r_refdef.scene.numentities;i++)
5094                 if (r_refdef.viewcache.entityvisible[i])
5095                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5096 }
5097
5098 //==================================================================================
5099
5100 extern cvar_t r_overheadsprites_pushback;
5101
5102 static void R_View_UpdateEntityLighting (void)
5103 {
5104         int i;
5105         entity_render_t *ent;
5106         vec3_t tempdiffusenormal, avg;
5107         vec_t f, fa, fd, fdd;
5108         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5109
5110         for (i = 0;i < r_refdef.scene.numentities;i++)
5111         {
5112                 ent = r_refdef.scene.entities[i];
5113
5114                 // skip unseen models
5115                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5116                         continue;
5117
5118                 // skip bsp models
5119                 if (ent->model && ent->model == cl.worldmodel)
5120                 {
5121                         // TODO: use modellight for r_ambient settings on world?
5122                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5123                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5124                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5125                         continue;
5126                 }
5127                 
5128                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5129                 {
5130                         // aleady updated by CSQC
5131                         // TODO: force modellight on BSP models in this case?
5132                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5133                 }
5134                 else
5135                 {
5136                         // fetch the lighting from the worldmodel data
5137                         VectorClear(ent->modellight_ambient);
5138                         VectorClear(ent->modellight_diffuse);
5139                         VectorClear(tempdiffusenormal);
5140                         if (ent->flags & RENDER_LIGHT)
5141                         {
5142                                 vec3_t org;
5143                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5144
5145                                 // complete lightning for lit sprites
5146                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5147                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5148                                 {
5149                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5150                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5151                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5152                                 }
5153                                 else
5154                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5155
5156                                 if(ent->flags & RENDER_EQUALIZE)
5157                                 {
5158                                         // first fix up ambient lighting...
5159                                         if(r_equalize_entities_minambient.value > 0)
5160                                         {
5161                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5162                                                 if(fd > 0)
5163                                                 {
5164                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5165                                                         if(fa < r_equalize_entities_minambient.value * fd)
5166                                                         {
5167                                                                 // solve:
5168                                                                 //   fa'/fd' = minambient
5169                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5170                                                                 //   ...
5171                                                                 //   fa' = fd' * minambient
5172                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5173                                                                 //   ...
5174                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5175                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5176                                                                 //   ...
5177                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5178                                                                 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
5179                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5180                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5181                                                         }
5182                                                 }
5183                                         }
5184
5185                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5186                                         {
5187                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5188                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5189                                                 f = fa + 0.25 * fd;
5190                                                 if(f > 0)
5191                                                 {
5192                                                         // adjust brightness and saturation to target
5193                                                         avg[0] = avg[1] = avg[2] = fa / f;
5194                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5195                                                         avg[0] = avg[1] = avg[2] = fd / f;
5196                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5197                                                 }
5198                                         }
5199                                 }
5200                         }
5201                         else // highly rare
5202                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5203                 }
5204
5205                 // move the light direction into modelspace coordinates for lighting code
5206                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5207                 if(VectorLength2(ent->modellight_lightdir) == 0)
5208                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5209                 VectorNormalize(ent->modellight_lightdir);
5210         }
5211 }
5212
5213 #define MAX_LINEOFSIGHTTRACES 64
5214
5215 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5216 {
5217         int i;
5218         vec3_t boxmins, boxmaxs;
5219         vec3_t start;
5220         vec3_t end;
5221         dp_model_t *model = r_refdef.scene.worldmodel;
5222
5223         if (!model || !model->brush.TraceLineOfSight)
5224                 return true;
5225
5226         // expand the box a little
5227         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5228         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5229         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5230         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5231         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5232         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5233
5234         // return true if eye is inside enlarged box
5235         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5236                 return true;
5237
5238         // try center
5239         VectorCopy(eye, start);
5240         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5241         if (model->brush.TraceLineOfSight(model, start, end))
5242                 return true;
5243
5244         // try various random positions
5245         for (i = 0;i < numsamples;i++)
5246         {
5247                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5248                 if (model->brush.TraceLineOfSight(model, start, end))
5249                         return true;
5250         }
5251
5252         return false;
5253 }
5254
5255
5256 static void R_View_UpdateEntityVisible (void)
5257 {
5258         int i;
5259         int renderimask;
5260         int samples;
5261         entity_render_t *ent;
5262
5263         if (r_refdef.envmap || r_fb.water.hideplayer)
5264                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5265         else if (chase_active.integer || r_fb.water.renderingscene)
5266                 renderimask = RENDER_VIEWMODEL;
5267         else
5268                 renderimask = RENDER_EXTERIORMODEL;
5269         if (!r_drawviewmodel.integer)
5270                 renderimask |= RENDER_VIEWMODEL;
5271         if (!r_drawexteriormodel.integer)
5272                 renderimask |= RENDER_EXTERIORMODEL;
5273         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5274         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5275         {
5276                 // worldmodel can check visibility
5277                 for (i = 0;i < r_refdef.scene.numentities;i++)
5278                 {
5279                         ent = r_refdef.scene.entities[i];
5280                         if (!(ent->flags & renderimask))
5281                         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)))
5282                         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))
5283                                 r_refdef.viewcache.entityvisible[i] = true;
5284                 }
5285         }
5286         else
5287         {
5288                 // no worldmodel or it can't check visibility
5289                 for (i = 0;i < r_refdef.scene.numentities;i++)
5290                 {
5291                         ent = r_refdef.scene.entities[i];
5292                         if (!(ent->flags & renderimask))
5293                         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)))
5294                                 r_refdef.viewcache.entityvisible[i] = true;
5295                 }
5296         }
5297         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5298                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5299         {
5300                 for (i = 0;i < r_refdef.scene.numentities;i++)
5301                 {
5302                         if (!r_refdef.viewcache.entityvisible[i])
5303                                 continue;
5304                         ent = r_refdef.scene.entities[i];
5305                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5306                         {
5307                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5308                                 if (samples < 0)
5309                                         continue; // temp entities do pvs only
5310                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5311                                         ent->last_trace_visibility = realtime;
5312                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5313                                         r_refdef.viewcache.entityvisible[i] = 0;
5314                         }
5315                 }
5316         }
5317 }
5318
5319 /// only used if skyrendermasked, and normally returns false
5320 static int R_DrawBrushModelsSky (void)
5321 {
5322         int i, sky;
5323         entity_render_t *ent;
5324
5325         sky = false;
5326         for (i = 0;i < r_refdef.scene.numentities;i++)
5327         {
5328                 if (!r_refdef.viewcache.entityvisible[i])
5329                         continue;
5330                 ent = r_refdef.scene.entities[i];
5331                 if (!ent->model || !ent->model->DrawSky)
5332                         continue;
5333                 ent->model->DrawSky(ent);
5334                 sky = true;
5335         }
5336         return sky;
5337 }
5338
5339 static void R_DrawNoModel(entity_render_t *ent);
5340 static void R_DrawModels(void)
5341 {
5342         int i;
5343         entity_render_t *ent;
5344
5345         for (i = 0;i < r_refdef.scene.numentities;i++)
5346         {
5347                 if (!r_refdef.viewcache.entityvisible[i])
5348                         continue;
5349                 ent = r_refdef.scene.entities[i];
5350                 r_refdef.stats[r_stat_entities]++;
5351                 /*
5352                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5353                 {
5354                         vec3_t f, l, u, o;
5355                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5356                         Con_Printf("R_DrawModels\n");
5357                         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]);
5358                         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);
5359                         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);
5360                 }
5361                 */
5362                 if (ent->model && ent->model->Draw != NULL)
5363                         ent->model->Draw(ent);
5364                 else
5365                         R_DrawNoModel(ent);
5366         }
5367 }
5368
5369 static void R_DrawModelsDepth(void)
5370 {
5371         int i;
5372         entity_render_t *ent;
5373
5374         for (i = 0;i < r_refdef.scene.numentities;i++)
5375         {
5376                 if (!r_refdef.viewcache.entityvisible[i])
5377                         continue;
5378                 ent = r_refdef.scene.entities[i];
5379                 if (ent->model && ent->model->DrawDepth != NULL)
5380                         ent->model->DrawDepth(ent);
5381         }
5382 }
5383
5384 static void R_DrawModelsDebug(void)
5385 {
5386         int i;
5387         entity_render_t *ent;
5388
5389         for (i = 0;i < r_refdef.scene.numentities;i++)
5390         {
5391                 if (!r_refdef.viewcache.entityvisible[i])
5392                         continue;
5393                 ent = r_refdef.scene.entities[i];
5394                 if (ent->model && ent->model->DrawDebug != NULL)
5395                         ent->model->DrawDebug(ent);
5396         }
5397 }
5398
5399 static void R_DrawModelsAddWaterPlanes(void)
5400 {
5401         int i;
5402         entity_render_t *ent;
5403
5404         for (i = 0;i < r_refdef.scene.numentities;i++)
5405         {
5406                 if (!r_refdef.viewcache.entityvisible[i])
5407                         continue;
5408                 ent = r_refdef.scene.entities[i];
5409                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5410                         ent->model->DrawAddWaterPlanes(ent);
5411         }
5412 }
5413
5414 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}};
5415
5416 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5417 {
5418         if (r_hdr_irisadaptation.integer)
5419         {
5420                 vec3_t p;
5421                 vec3_t ambient;
5422                 vec3_t diffuse;
5423                 vec3_t diffusenormal;
5424                 vec3_t forward;
5425                 vec_t brightness = 0.0f;
5426                 vec_t goal;
5427                 vec_t current;
5428                 vec_t d;
5429                 int c;
5430                 VectorCopy(r_refdef.view.forward, forward);
5431                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5432                 {
5433                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5434                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5435                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5436                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5437                         d = DotProduct(forward, diffusenormal);
5438                         brightness += VectorLength(ambient);
5439                         if (d > 0)
5440                                 brightness += d * VectorLength(diffuse);
5441                 }
5442                 brightness *= 1.0f / c;
5443                 brightness += 0.00001f; // make sure it's never zero
5444                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5445                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5446                 current = r_hdr_irisadaptation_value.value;
5447                 if (current < goal)
5448                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5449                 else if (current > goal)
5450                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5451                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5452                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5453         }
5454         else if (r_hdr_irisadaptation_value.value != 1.0f)
5455                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5456 }
5457
5458 static void R_View_SetFrustum(const int *scissor)
5459 {
5460         int i;
5461         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5462         vec3_t forward, left, up, origin, v;
5463
5464         if(scissor)
5465         {
5466                 // flipped x coordinates (because x points left here)
5467                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5468                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5469
5470                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5471                 switch(vid.renderpath)
5472                 {
5473                         case RENDERPATH_D3D9:
5474                         case RENDERPATH_D3D10:
5475                         case RENDERPATH_D3D11:
5476                                 // non-flipped y coordinates
5477                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5478                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5479                                 break;
5480                         case RENDERPATH_SOFT:
5481                         case RENDERPATH_GL11:
5482                         case RENDERPATH_GL13:
5483                         case RENDERPATH_GL20:
5484                         case RENDERPATH_GLES1:
5485                         case RENDERPATH_GLES2:
5486                                 // non-flipped y coordinates
5487                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5488                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5489                                 break;
5490                 }
5491         }
5492
5493         // we can't trust r_refdef.view.forward and friends in reflected scenes
5494         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5495
5496 #if 0
5497         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5498         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5499         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5500         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5501         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5502         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5503         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5504         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5505         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5506         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5507         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5508         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5509 #endif
5510
5511 #if 0
5512         zNear = r_refdef.nearclip;
5513         nudge = 1.0 - 1.0 / (1<<23);
5514         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5515         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5516         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5517         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5518         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5519         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5520         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5521         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5522 #endif
5523
5524
5525
5526 #if 0
5527         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5528         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5529         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5530         r_refdef.view.frustum[0].dist = m[15] - m[12];
5531
5532         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5533         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5534         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5535         r_refdef.view.frustum[1].dist = m[15] + m[12];
5536
5537         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5538         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5539         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5540         r_refdef.view.frustum[2].dist = m[15] - m[13];
5541
5542         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5543         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5544         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5545         r_refdef.view.frustum[3].dist = m[15] + m[13];
5546
5547         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5548         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5549         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5550         r_refdef.view.frustum[4].dist = m[15] - m[14];
5551
5552         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5553         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5554         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5555         r_refdef.view.frustum[5].dist = m[15] + m[14];
5556 #endif
5557
5558         if (r_refdef.view.useperspective)
5559         {
5560                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5561                 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]);
5562                 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]);
5563                 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]);
5564                 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]);
5565
5566                 // then the normals from the corners relative to origin
5567                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5568                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5569                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5570                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5571
5572                 // in a NORMAL view, forward cross left == up
5573                 // in a REFLECTED view, forward cross left == down
5574                 // so our cross products above need to be adjusted for a left handed coordinate system
5575                 CrossProduct(forward, left, v);
5576                 if(DotProduct(v, up) < 0)
5577                 {
5578                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5579                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5580                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5581                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5582                 }
5583
5584                 // Leaving those out was a mistake, those were in the old code, and they
5585                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5586                 // I couldn't reproduce it after adding those normalizations. --blub
5587                 VectorNormalize(r_refdef.view.frustum[0].normal);
5588                 VectorNormalize(r_refdef.view.frustum[1].normal);
5589                 VectorNormalize(r_refdef.view.frustum[2].normal);
5590                 VectorNormalize(r_refdef.view.frustum[3].normal);
5591
5592                 // make the corners absolute
5593                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5594                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5595                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5596                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5597
5598                 // one more normal
5599                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5600
5601                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5602                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5603                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5604                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5605                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5606         }
5607         else
5608         {
5609                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5610                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5611                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5612                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5613                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5614                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5615                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5616                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5617                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5618                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5619         }
5620         r_refdef.view.numfrustumplanes = 5;
5621
5622         if (r_refdef.view.useclipplane)
5623         {
5624                 r_refdef.view.numfrustumplanes = 6;
5625                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5626         }
5627
5628         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5629                 PlaneClassify(r_refdef.view.frustum + i);
5630
5631         // LordHavoc: note to all quake engine coders, Quake had a special case
5632         // for 90 degrees which assumed a square view (wrong), so I removed it,
5633         // Quake2 has it disabled as well.
5634
5635         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5636         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5637         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5638         //PlaneClassify(&frustum[0]);
5639
5640         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5641         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5642         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5643         //PlaneClassify(&frustum[1]);
5644
5645         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5646         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5647         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5648         //PlaneClassify(&frustum[2]);
5649
5650         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5651         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5652         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5653         //PlaneClassify(&frustum[3]);
5654
5655         // nearclip plane
5656         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5657         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5658         //PlaneClassify(&frustum[4]);
5659 }
5660
5661 static void R_View_UpdateWithScissor(const int *myscissor)
5662 {
5663         R_Main_ResizeViewCache();
5664         R_View_SetFrustum(myscissor);
5665         R_View_WorldVisibility(r_refdef.view.useclipplane);
5666         R_View_UpdateEntityVisible();
5667         R_View_UpdateEntityLighting();
5668 }
5669
5670 static void R_View_Update(void)
5671 {
5672         R_Main_ResizeViewCache();
5673         R_View_SetFrustum(NULL);
5674         R_View_WorldVisibility(r_refdef.view.useclipplane);
5675         R_View_UpdateEntityVisible();
5676         R_View_UpdateEntityLighting();
5677 }
5678
5679 float viewscalefpsadjusted = 1.0f;
5680
5681 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5682 {
5683         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5684         scale = bound(0.03125f, scale, 1.0f);
5685         *outwidth = (int)ceil(width * scale);
5686         *outheight = (int)ceil(height * scale);
5687 }
5688
5689 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5690 {
5691         const float *customclipplane = NULL;
5692         float plane[4];
5693         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5694         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5695         {
5696                 // LordHavoc: couldn't figure out how to make this approach the
5697                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5698                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5699                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5700                         dist = r_refdef.view.clipplane.dist;
5701                 plane[0] = r_refdef.view.clipplane.normal[0];
5702                 plane[1] = r_refdef.view.clipplane.normal[1];
5703                 plane[2] = r_refdef.view.clipplane.normal[2];
5704                 plane[3] = -dist;
5705                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5706         }
5707
5708         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5709         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5710
5711         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5712         if (!r_refdef.view.useperspective)
5713                 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);
5714         else if (vid.stencil && r_useinfinitefarclip.integer)
5715                 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);
5716         else
5717                 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);
5718         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5719         R_SetViewport(&r_refdef.view.viewport);
5720         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5721         {
5722                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5723                 float screenplane[4];
5724                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5725                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5726                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5727                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5728                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5729         }
5730 }
5731
5732 void R_EntityMatrix(const matrix4x4_t *matrix)
5733 {
5734         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5735         {
5736                 gl_modelmatrixchanged = false;
5737                 gl_modelmatrix = *matrix;
5738                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5739                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5740                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5741                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5742                 CHECKGLERROR
5743                 switch(vid.renderpath)
5744                 {
5745                 case RENDERPATH_D3D9:
5746 #ifdef SUPPORTD3D
5747                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5748                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5749 #endif
5750                         break;
5751                 case RENDERPATH_D3D10:
5752                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5753                         break;
5754                 case RENDERPATH_D3D11:
5755                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5756                         break;
5757                 case RENDERPATH_GL11:
5758                 case RENDERPATH_GL13:
5759                 case RENDERPATH_GLES1:
5760 #ifndef USE_GLES2
5761                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5762 #endif
5763                         break;
5764                 case RENDERPATH_SOFT:
5765                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5766                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5767                         break;
5768                 case RENDERPATH_GL20:
5769                 case RENDERPATH_GLES2:
5770                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5771                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5772                         break;
5773                 }
5774         }
5775 }
5776
5777 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5778 {
5779         r_viewport_t viewport;
5780
5781         CHECKGLERROR
5782
5783         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5784         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);
5785         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5786         R_SetViewport(&viewport);
5787         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5788         GL_Color(1, 1, 1, 1);
5789         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5790         GL_BlendFunc(GL_ONE, GL_ZERO);
5791         GL_ScissorTest(false);
5792         GL_DepthMask(false);
5793         GL_DepthRange(0, 1);
5794         GL_DepthTest(false);
5795         GL_DepthFunc(GL_LEQUAL);
5796         R_EntityMatrix(&identitymatrix);
5797         R_Mesh_ResetTextureState();
5798         GL_PolygonOffset(0, 0);
5799         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5800         switch(vid.renderpath)
5801         {
5802         case RENDERPATH_GL11:
5803         case RENDERPATH_GL13:
5804         case RENDERPATH_GL20:
5805         case RENDERPATH_GLES1:
5806         case RENDERPATH_GLES2:
5807                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5808                 break;
5809         case RENDERPATH_D3D9:
5810         case RENDERPATH_D3D10:
5811         case RENDERPATH_D3D11:
5812         case RENDERPATH_SOFT:
5813                 break;
5814         }
5815         GL_CullFace(GL_NONE);
5816
5817         CHECKGLERROR
5818 }
5819
5820 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5821 {
5822         DrawQ_Finish();
5823
5824         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5825 }
5826
5827 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5828 {
5829         DrawQ_Finish();
5830
5831         R_SetupView(true, fbo, depthtexture, colortexture);
5832         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5833         GL_Color(1, 1, 1, 1);
5834         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5835         GL_BlendFunc(GL_ONE, GL_ZERO);
5836         GL_ScissorTest(true);
5837         GL_DepthMask(true);
5838         GL_DepthRange(0, 1);
5839         GL_DepthTest(true);
5840         GL_DepthFunc(GL_LEQUAL);
5841         R_EntityMatrix(&identitymatrix);
5842         R_Mesh_ResetTextureState();
5843         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5844         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5845         switch(vid.renderpath)
5846         {
5847         case RENDERPATH_GL11:
5848         case RENDERPATH_GL13:
5849         case RENDERPATH_GL20:
5850         case RENDERPATH_GLES1:
5851         case RENDERPATH_GLES2:
5852                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5853                 break;
5854         case RENDERPATH_D3D9:
5855         case RENDERPATH_D3D10:
5856         case RENDERPATH_D3D11:
5857         case RENDERPATH_SOFT:
5858                 break;
5859         }
5860         GL_CullFace(r_refdef.view.cullface_back);
5861 }
5862
5863 /*
5864 ================
5865 R_RenderView_UpdateViewVectors
5866 ================
5867 */
5868 void R_RenderView_UpdateViewVectors(void)
5869 {
5870         // break apart the view matrix into vectors for various purposes
5871         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5872         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5873         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5874         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5875         // make an inverted copy of the view matrix for tracking sprites
5876         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5877 }
5878
5879 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5880 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5881
5882 static void R_Water_StartFrame(void)
5883 {
5884         int i;
5885         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5886         r_waterstate_waterplane_t *p;
5887         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;
5888
5889         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5890                 return;
5891
5892         switch(vid.renderpath)
5893         {
5894         case RENDERPATH_GL20:
5895         case RENDERPATH_D3D9:
5896         case RENDERPATH_D3D10:
5897         case RENDERPATH_D3D11:
5898         case RENDERPATH_SOFT:
5899         case RENDERPATH_GLES2:
5900                 break;
5901         case RENDERPATH_GL11:
5902         case RENDERPATH_GL13:
5903         case RENDERPATH_GLES1:
5904                 return;
5905         }
5906
5907         // set waterwidth and waterheight to the water resolution that will be
5908         // used (often less than the screen resolution for faster rendering)
5909         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5910
5911         // calculate desired texture sizes
5912         // can't use water if the card does not support the texture size
5913         if (!r_water.integer || r_showsurfaces.integer)
5914                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5915         else if (vid.support.arb_texture_non_power_of_two)
5916         {
5917                 texturewidth = waterwidth;
5918                 textureheight = waterheight;
5919                 camerawidth = waterwidth;
5920                 cameraheight = waterheight;
5921         }
5922         else
5923         {
5924                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5925                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5926                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5927                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5928         }
5929
5930         // allocate textures as needed
5931         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))
5932         {
5933                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5934                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5935                 {
5936                         if (p->texture_refraction)
5937                                 R_FreeTexture(p->texture_refraction);
5938                         p->texture_refraction = NULL;
5939                         if (p->fbo_refraction)
5940                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5941                         p->fbo_refraction = 0;
5942                         if (p->texture_reflection)
5943                                 R_FreeTexture(p->texture_reflection);
5944                         p->texture_reflection = NULL;
5945                         if (p->fbo_reflection)
5946                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5947                         p->fbo_reflection = 0;
5948                         if (p->texture_camera)
5949                                 R_FreeTexture(p->texture_camera);
5950                         p->texture_camera = NULL;
5951                         if (p->fbo_camera)
5952                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5953                         p->fbo_camera = 0;
5954                 }
5955                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5956                 r_fb.water.texturewidth = texturewidth;
5957                 r_fb.water.textureheight = textureheight;
5958                 r_fb.water.camerawidth = camerawidth;
5959                 r_fb.water.cameraheight = cameraheight;
5960         }
5961
5962         if (r_fb.water.texturewidth)
5963         {
5964                 int scaledwidth, scaledheight;
5965
5966                 r_fb.water.enabled = true;
5967
5968                 // water resolution is usually reduced
5969                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5970                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5971                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5972
5973                 // set up variables that will be used in shader setup
5974                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5975                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5976                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5977                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5978         }
5979
5980         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5981         r_fb.water.numwaterplanes = 0;
5982 }
5983
5984 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5985 {
5986         int planeindex, bestplaneindex, vertexindex;
5987         vec3_t mins, maxs, normal, center, v, n;
5988         vec_t planescore, bestplanescore;
5989         mplane_t plane;
5990         r_waterstate_waterplane_t *p;
5991         texture_t *t = R_GetCurrentTexture(surface->texture);
5992
5993         rsurface.texture = t;
5994         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5995         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5996         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5997                 return;
5998         // average the vertex normals, find the surface bounds (after deformvertexes)
5999         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6000         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6001         VectorCopy(n, normal);
6002         VectorCopy(v, mins);
6003         VectorCopy(v, maxs);
6004         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6005         {
6006                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6007                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6008                 VectorAdd(normal, n, normal);
6009                 mins[0] = min(mins[0], v[0]);
6010                 mins[1] = min(mins[1], v[1]);
6011                 mins[2] = min(mins[2], v[2]);
6012                 maxs[0] = max(maxs[0], v[0]);
6013                 maxs[1] = max(maxs[1], v[1]);
6014                 maxs[2] = max(maxs[2], v[2]);
6015         }
6016         VectorNormalize(normal);
6017         VectorMAM(0.5f, mins, 0.5f, maxs, center);
6018
6019         VectorCopy(normal, plane.normal);
6020         VectorNormalize(plane.normal);
6021         plane.dist = DotProduct(center, plane.normal);
6022         PlaneClassify(&plane);
6023         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6024         {
6025                 // skip backfaces (except if nocullface is set)
6026 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6027 //                      return;
6028                 VectorNegate(plane.normal, plane.normal);
6029                 plane.dist *= -1;
6030                 PlaneClassify(&plane);
6031         }
6032
6033
6034         // find a matching plane if there is one
6035         bestplaneindex = -1;
6036         bestplanescore = 1048576.0f;
6037         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6038         {
6039                 if(p->camera_entity == t->camera_entity)
6040                 {
6041                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6042                         if (bestplaneindex < 0 || bestplanescore > planescore)
6043                         {
6044                                 bestplaneindex = planeindex;
6045                                 bestplanescore = planescore;
6046                         }
6047                 }
6048         }
6049         planeindex = bestplaneindex;
6050
6051         // if this surface does not fit any known plane rendered this frame, add one
6052         if (planeindex < 0 || bestplanescore > 0.001f)
6053         {
6054                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6055                 {
6056                         // store the new plane
6057                         planeindex = r_fb.water.numwaterplanes++;
6058                         p = r_fb.water.waterplanes + planeindex;
6059                         p->plane = plane;
6060                         // clear materialflags and pvs
6061                         p->materialflags = 0;
6062                         p->pvsvalid = false;
6063                         p->camera_entity = t->camera_entity;
6064                         VectorCopy(mins, p->mins);
6065                         VectorCopy(maxs, p->maxs);
6066                 }
6067                 else
6068                 {
6069                         // We're totally screwed.
6070                         return;
6071                 }
6072         }
6073         else
6074         {
6075                 // merge mins/maxs when we're adding this surface to the plane
6076                 p = r_fb.water.waterplanes + planeindex;
6077                 p->mins[0] = min(p->mins[0], mins[0]);
6078                 p->mins[1] = min(p->mins[1], mins[1]);
6079                 p->mins[2] = min(p->mins[2], mins[2]);
6080                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6081                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6082                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6083         }
6084         // merge this surface's materialflags into the waterplane
6085         p->materialflags |= t->currentmaterialflags;
6086         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6087         {
6088                 // merge this surface's PVS into the waterplane
6089                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6090                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6091                 {
6092                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6093                         p->pvsvalid = true;
6094                 }
6095         }
6096 }
6097
6098 extern cvar_t r_drawparticles;
6099 extern cvar_t r_drawdecals;
6100
6101 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6102 {
6103         int myscissor[4];
6104         r_refdef_view_t originalview;
6105         r_refdef_view_t myview;
6106         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;
6107         r_waterstate_waterplane_t *p;
6108         vec3_t visorigin;
6109         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;
6110         char vabuf[1024];
6111
6112         originalview = r_refdef.view;
6113
6114         // lowquality hack, temporarily shut down some cvars and restore afterwards
6115         qualityreduction = r_water_lowquality.integer;
6116         if (qualityreduction > 0)
6117         {
6118                 if (qualityreduction >= 1)
6119                 {
6120                         old_r_shadows = r_shadows.integer;
6121                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6122                         old_r_dlight = r_shadow_realtime_dlight.integer;
6123                         Cvar_SetValueQuick(&r_shadows, 0);
6124                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6125                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6126                 }
6127                 if (qualityreduction >= 2)
6128                 {
6129                         old_r_dynamic = r_dynamic.integer;
6130                         old_r_particles = r_drawparticles.integer;
6131                         old_r_decals = r_drawdecals.integer;
6132                         Cvar_SetValueQuick(&r_dynamic, 0);
6133                         Cvar_SetValueQuick(&r_drawparticles, 0);
6134                         Cvar_SetValueQuick(&r_drawdecals, 0);
6135                 }
6136         }
6137
6138         // make sure enough textures are allocated
6139         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6140         {
6141                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6142                         continue;
6143                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6144                 {
6145                         if (!p->texture_refraction)
6146                                 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);
6147                         if (!p->texture_refraction)
6148                                 goto error;
6149                         if (usewaterfbo)
6150                         {
6151                                 if (r_fb.water.depthtexture == NULL)
6152                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6153                                 if (p->fbo_refraction == 0)
6154                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6155                         }
6156                 }
6157                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6158                 {
6159                         if (!p->texture_camera)
6160                                 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);
6161                         if (!p->texture_camera)
6162                                 goto error;
6163                         if (usewaterfbo)
6164                         {
6165                                 if (r_fb.water.depthtexture == NULL)
6166                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6167                                 if (p->fbo_camera == 0)
6168                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6169                         }
6170                 }
6171
6172                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6173                 {
6174                         if (!p->texture_reflection)
6175                                 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);
6176                         if (!p->texture_reflection)
6177                                 goto error;
6178                         if (usewaterfbo)
6179                         {
6180                                 if (r_fb.water.depthtexture == NULL)
6181                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6182                                 if (p->fbo_reflection == 0)
6183                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6184                         }
6185                 }
6186         }
6187
6188         // render views
6189         r_refdef.view = originalview;
6190         r_refdef.view.showdebug = false;
6191         r_refdef.view.width = r_fb.water.waterwidth;
6192         r_refdef.view.height = r_fb.water.waterheight;
6193         r_refdef.view.useclipplane = true;
6194         myview = r_refdef.view;
6195         r_fb.water.renderingscene = true;
6196         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6197         {
6198                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6199                         continue;
6200                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6201                 {
6202                         r_refdef.view = myview;
6203                         if(r_water_scissormode.integer)
6204                         {
6205                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6206                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6207                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6208                         }
6209
6210                         // render reflected scene and copy into texture
6211                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6212                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6213                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6214                         r_refdef.view.clipplane = p->plane;
6215                         // reverse the cullface settings for this render
6216                         r_refdef.view.cullface_front = GL_FRONT;
6217                         r_refdef.view.cullface_back = GL_BACK;
6218                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6219                         {
6220                                 r_refdef.view.usecustompvs = true;
6221                                 if (p->pvsvalid)
6222                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6223                                 else
6224                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6225                         }
6226
6227                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6228                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6229                         R_ClearScreen(r_refdef.fogenabled);
6230                         if(r_water_scissormode.integer & 2)
6231                                 R_View_UpdateWithScissor(myscissor);
6232                         else
6233                                 R_View_Update();
6234                         R_AnimCache_CacheVisibleEntities();
6235                         if(r_water_scissormode.integer & 1)
6236                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6237                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6238
6239                         if (!p->fbo_reflection)
6240                                 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);
6241                         r_fb.water.hideplayer = false;
6242                 }
6243
6244                 // render the normal view scene and copy into texture
6245                 // (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)
6246                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6247                 {
6248                         r_refdef.view = myview;
6249                         if(r_water_scissormode.integer)
6250                         {
6251                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6252                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6253                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6254                         }
6255
6256                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6257
6258                         r_refdef.view.clipplane = p->plane;
6259                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6260                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6261
6262                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6263                         {
6264                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6265                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6266                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6267                                 R_RenderView_UpdateViewVectors();
6268                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6269                                 {
6270                                         r_refdef.view.usecustompvs = true;
6271                                         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);
6272                                 }
6273                         }
6274
6275                         PlaneClassify(&r_refdef.view.clipplane);
6276
6277                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6278                         R_ClearScreen(r_refdef.fogenabled);
6279                         if(r_water_scissormode.integer & 2)
6280                                 R_View_UpdateWithScissor(myscissor);
6281                         else
6282                                 R_View_Update();
6283                         R_AnimCache_CacheVisibleEntities();
6284                         if(r_water_scissormode.integer & 1)
6285                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6286                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6287
6288                         if (!p->fbo_refraction)
6289                                 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);
6290                         r_fb.water.hideplayer = false;
6291                 }
6292                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6293                 {
6294                         r_refdef.view = myview;
6295
6296                         r_refdef.view.clipplane = p->plane;
6297                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6298                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6299
6300                         r_refdef.view.width = r_fb.water.camerawidth;
6301                         r_refdef.view.height = r_fb.water.cameraheight;
6302                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6303                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6304                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6305                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6306
6307                         if(p->camera_entity)
6308                         {
6309                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6310                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6311                         }
6312
6313                         // note: all of the view is used for displaying... so
6314                         // there is no use in scissoring
6315
6316                         // reverse the cullface settings for this render
6317                         r_refdef.view.cullface_front = GL_FRONT;
6318                         r_refdef.view.cullface_back = GL_BACK;
6319                         // also reverse the view matrix
6320                         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
6321                         R_RenderView_UpdateViewVectors();
6322                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6323                         {
6324                                 r_refdef.view.usecustompvs = true;
6325                                 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);
6326                         }
6327                         
6328                         // camera needs no clipplane
6329                         r_refdef.view.useclipplane = false;
6330
6331                         PlaneClassify(&r_refdef.view.clipplane);
6332
6333                         r_fb.water.hideplayer = false;
6334
6335                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6336                         R_ClearScreen(r_refdef.fogenabled);
6337                         R_View_Update();
6338                         R_AnimCache_CacheVisibleEntities();
6339                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6340
6341                         if (!p->fbo_camera)
6342                                 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);
6343                         r_fb.water.hideplayer = false;
6344                 }
6345
6346         }
6347         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6348         r_fb.water.renderingscene = false;
6349         r_refdef.view = originalview;
6350         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6351         if (!r_fb.water.depthtexture)
6352                 R_ClearScreen(r_refdef.fogenabled);
6353         R_View_Update();
6354         R_AnimCache_CacheVisibleEntities();
6355         goto finish;
6356 error:
6357         r_refdef.view = originalview;
6358         r_fb.water.renderingscene = false;
6359         Cvar_SetValueQuick(&r_water, 0);
6360         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6361 finish:
6362         // lowquality hack, restore cvars
6363         if (qualityreduction > 0)
6364         {
6365                 if (qualityreduction >= 1)
6366                 {
6367                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6368                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6369                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6370                 }
6371                 if (qualityreduction >= 2)
6372                 {
6373                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6374                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6375                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6376                 }
6377         }
6378 }
6379
6380 static void R_Bloom_StartFrame(void)
6381 {
6382         int i;
6383         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6384         int viewwidth, viewheight;
6385         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6386         textype_t textype = TEXTYPE_COLORBUFFER;
6387
6388         switch (vid.renderpath)
6389         {
6390         case RENDERPATH_GL20:
6391                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6392                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6393                 {
6394                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6395                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6396                 }
6397                 break;
6398         case RENDERPATH_GL11:
6399         case RENDERPATH_GL13:
6400         case RENDERPATH_GLES1:
6401         case RENDERPATH_GLES2:
6402         case RENDERPATH_D3D9:
6403         case RENDERPATH_D3D10:
6404         case RENDERPATH_D3D11:
6405                 r_fb.usedepthtextures = false;
6406                 break;
6407         case RENDERPATH_SOFT:
6408                 r_fb.usedepthtextures = true;
6409                 break;
6410         }
6411
6412         if (r_viewscale_fpsscaling.integer)
6413         {
6414                 double actualframetime;
6415                 double targetframetime;
6416                 double adjust;
6417                 actualframetime = r_refdef.lastdrawscreentime;
6418                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6419                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6420                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6421                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6422                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6423                 viewscalefpsadjusted += adjust;
6424                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6425         }
6426         else
6427                 viewscalefpsadjusted = 1.0f;
6428
6429         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6430
6431         switch(vid.renderpath)
6432         {
6433         case RENDERPATH_GL20:
6434         case RENDERPATH_D3D9:
6435         case RENDERPATH_D3D10:
6436         case RENDERPATH_D3D11:
6437         case RENDERPATH_SOFT:
6438         case RENDERPATH_GLES2:
6439                 break;
6440         case RENDERPATH_GL11:
6441         case RENDERPATH_GL13:
6442         case RENDERPATH_GLES1:
6443                 return;
6444         }
6445
6446         // set bloomwidth and bloomheight to the bloom resolution that will be
6447         // used (often less than the screen resolution for faster rendering)
6448         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6449         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6450         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6451         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6452         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6453
6454         // calculate desired texture sizes
6455         if (vid.support.arb_texture_non_power_of_two)
6456         {
6457                 screentexturewidth = vid.width;
6458                 screentextureheight = vid.height;
6459                 bloomtexturewidth = r_fb.bloomwidth;
6460                 bloomtextureheight = r_fb.bloomheight;
6461         }
6462         else
6463         {
6464                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6465                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6466                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6467                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6468         }
6469
6470         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))
6471         {
6472                 Cvar_SetValueQuick(&r_bloom, 0);
6473                 Cvar_SetValueQuick(&r_motionblur, 0);
6474                 Cvar_SetValueQuick(&r_damageblur, 0);
6475         }
6476
6477         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6478          && !r_bloom.integer
6479          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6480          && !useviewfbo
6481          && r_viewscale.value == 1.0f
6482          && !r_viewscale_fpsscaling.integer)
6483                 screentexturewidth = screentextureheight = 0;
6484         if (!r_bloom.integer)
6485                 bloomtexturewidth = bloomtextureheight = 0;
6486
6487         // allocate textures as needed
6488         if (r_fb.screentexturewidth != screentexturewidth
6489          || r_fb.screentextureheight != screentextureheight
6490          || r_fb.bloomtexturewidth != bloomtexturewidth
6491          || r_fb.bloomtextureheight != bloomtextureheight
6492          || r_fb.textype != textype
6493          || useviewfbo != (r_fb.fbo != 0))
6494         {
6495                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6496                 {
6497                         if (r_fb.bloomtexture[i])
6498                                 R_FreeTexture(r_fb.bloomtexture[i]);
6499                         r_fb.bloomtexture[i] = NULL;
6500
6501                         if (r_fb.bloomfbo[i])
6502                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6503                         r_fb.bloomfbo[i] = 0;
6504                 }
6505
6506                 if (r_fb.fbo)
6507                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6508                 r_fb.fbo = 0;
6509
6510                 if (r_fb.colortexture)
6511                         R_FreeTexture(r_fb.colortexture);
6512                 r_fb.colortexture = NULL;
6513
6514                 if (r_fb.depthtexture)
6515                         R_FreeTexture(r_fb.depthtexture);
6516                 r_fb.depthtexture = NULL;
6517
6518                 if (r_fb.ghosttexture)
6519                         R_FreeTexture(r_fb.ghosttexture);
6520                 r_fb.ghosttexture = NULL;
6521
6522                 r_fb.screentexturewidth = screentexturewidth;
6523                 r_fb.screentextureheight = screentextureheight;
6524                 r_fb.bloomtexturewidth = bloomtexturewidth;
6525                 r_fb.bloomtextureheight = bloomtextureheight;
6526                 r_fb.textype = textype;
6527
6528                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6529                 {
6530                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6531                                 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);
6532                         r_fb.ghosttexture_valid = false;
6533                         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);
6534                         if (useviewfbo)
6535                         {
6536                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6537                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6538                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6539                         }
6540                 }
6541
6542                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6543                 {
6544                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6545                         {
6546                                 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);
6547                                 if (useviewfbo)
6548                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6549                         }
6550                 }
6551         }
6552
6553         // bloom texture is a different resolution
6554         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6555         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6556         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6557         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6558         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6559
6560         // set up a texcoord array for the full resolution screen image
6561         // (we have to keep this around to copy back during final render)
6562         r_fb.screentexcoord2f[0] = 0;
6563         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6564         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6565         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6566         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6567         r_fb.screentexcoord2f[5] = 0;
6568         r_fb.screentexcoord2f[6] = 0;
6569         r_fb.screentexcoord2f[7] = 0;
6570
6571         if(r_fb.fbo) 
6572         {
6573                 for (i = 1;i < 8;i += 2)
6574                 {
6575                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6576                 }
6577         }
6578
6579         // set up a texcoord array for the reduced resolution bloom image
6580         // (which will be additive blended over the screen image)
6581         r_fb.bloomtexcoord2f[0] = 0;
6582         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6583         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6584         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6585         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6586         r_fb.bloomtexcoord2f[5] = 0;
6587         r_fb.bloomtexcoord2f[6] = 0;
6588         r_fb.bloomtexcoord2f[7] = 0;
6589
6590         switch(vid.renderpath)
6591         {
6592         case RENDERPATH_GL11:
6593         case RENDERPATH_GL13:
6594         case RENDERPATH_GL20:
6595         case RENDERPATH_SOFT:
6596         case RENDERPATH_GLES1:
6597         case RENDERPATH_GLES2:
6598                 break;
6599         case RENDERPATH_D3D9:
6600         case RENDERPATH_D3D10:
6601         case RENDERPATH_D3D11:
6602                 for (i = 0;i < 4;i++)
6603                 {
6604                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6605                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6606                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6607                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6608                 }
6609                 break;
6610         }
6611
6612         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6613
6614         if (r_fb.fbo)
6615                 r_refdef.view.clear = true;
6616 }
6617
6618 static void R_Bloom_MakeTexture(void)
6619 {
6620         int x, range, dir;
6621         float xoffset, yoffset, r, brighten;
6622         rtexture_t *intex;
6623         float colorscale = r_bloom_colorscale.value;
6624
6625         r_refdef.stats[r_stat_bloom]++;
6626     
6627 #if 0
6628     // this copy is unnecessary since it happens in R_BlendView already
6629         if (!r_fb.fbo)
6630         {
6631                 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);
6632                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6633         }
6634 #endif
6635
6636         // scale down screen texture to the bloom texture size
6637         CHECKGLERROR
6638         r_fb.bloomindex = 0;
6639         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6640         R_SetViewport(&r_fb.bloomviewport);
6641         GL_DepthTest(false);
6642         GL_BlendFunc(GL_ONE, GL_ZERO);
6643         GL_Color(colorscale, colorscale, colorscale, 1);
6644         // 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...
6645         switch(vid.renderpath)
6646         {
6647         case RENDERPATH_GL11:
6648         case RENDERPATH_GL13:
6649         case RENDERPATH_GL20:
6650         case RENDERPATH_GLES1:
6651         case RENDERPATH_GLES2:
6652         case RENDERPATH_SOFT:
6653                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6654                 break;
6655         case RENDERPATH_D3D9:
6656         case RENDERPATH_D3D10:
6657         case RENDERPATH_D3D11:
6658                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6659                 break;
6660         }
6661         // TODO: do boxfilter scale-down in shader?
6662         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6663         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6664         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6665
6666         // we now have a properly scaled bloom image
6667         if (!r_fb.bloomfbo[r_fb.bloomindex])
6668         {
6669                 // copy it into the bloom texture
6670                 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);
6671                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6672         }
6673
6674         // multiply bloom image by itself as many times as desired
6675         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6676         {
6677                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6678                 r_fb.bloomindex ^= 1;
6679                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6680                 x *= 2;
6681                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6682                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6683                 {
6684                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6685                         GL_Color(r,r,r,1); // apply fix factor
6686                 }
6687                 else
6688                 {
6689                         if(x <= 2)
6690                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6691                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6692                         GL_Color(1,1,1,1); // no fix factor supported here
6693                 }
6694                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6695                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6696                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6697                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6698
6699                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6700                 {
6701                         // copy the darkened image to a texture
6702                         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);
6703                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6704                 }
6705         }
6706
6707         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6708         brighten = r_bloom_brighten.value;
6709         brighten = sqrt(brighten);
6710         if(range >= 1)
6711                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6712
6713         for (dir = 0;dir < 2;dir++)
6714         {
6715                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6716                 r_fb.bloomindex ^= 1;
6717                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6718                 // blend on at multiple vertical offsets to achieve a vertical blur
6719                 // TODO: do offset blends using GLSL
6720                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6721                 GL_BlendFunc(GL_ONE, GL_ZERO);
6722                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6723                 for (x = -range;x <= range;x++)
6724                 {
6725                         if (!dir){xoffset = 0;yoffset = x;}
6726                         else {xoffset = x;yoffset = 0;}
6727                         xoffset /= (float)r_fb.bloomtexturewidth;
6728                         yoffset /= (float)r_fb.bloomtextureheight;
6729                         // compute a texcoord array with the specified x and y offset
6730                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6731                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6732                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6733                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6734                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6735                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6736                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6737                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6738                         // this r value looks like a 'dot' particle, fading sharply to
6739                         // black at the edges
6740                         // (probably not realistic but looks good enough)
6741                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6742                         //r = brighten/(range*2+1);
6743                         r = brighten / (range * 2 + 1);
6744                         if(range >= 1)
6745                                 r *= (1 - x*x/(float)(range*range));
6746                         GL_Color(r, r, r, 1);
6747                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6748                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6749                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6750                         GL_BlendFunc(GL_ONE, GL_ONE);
6751                 }
6752
6753                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6754                 {
6755                         // copy the vertically or horizontally blurred bloom view to a texture
6756                         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);
6757                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6758                 }
6759         }
6760 }
6761
6762 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6763 {
6764         unsigned int permutation;
6765         float uservecs[4][4];
6766
6767         R_EntityMatrix(&identitymatrix);
6768
6769         switch (vid.renderpath)
6770         {
6771         case RENDERPATH_GL20:
6772         case RENDERPATH_D3D9:
6773         case RENDERPATH_D3D10:
6774         case RENDERPATH_D3D11:
6775         case RENDERPATH_SOFT:
6776         case RENDERPATH_GLES2:
6777                 permutation =
6778                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6779                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6780                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6781                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6782                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6783
6784                 if (r_fb.colortexture)
6785                 {
6786                         if (!r_fb.fbo)
6787                         {
6788                                 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);
6789                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6790                         }
6791
6792                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6793                         {
6794                                 // declare variables
6795                                 float blur_factor, blur_mouseaccel, blur_velocity;
6796                                 static float blur_average; 
6797                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6798
6799                                 // set a goal for the factoring
6800                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6801                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6802                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6803                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6804                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6805                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6806
6807                                 // from the goal, pick an averaged value between goal and last value
6808                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6809                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6810
6811                                 // enforce minimum amount of blur 
6812                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6813
6814                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6815
6816                                 // calculate values into a standard alpha
6817                                 cl.motionbluralpha = 1 - exp(-
6818                                                 (
6819                                                  (r_motionblur.value * blur_factor / 80)
6820                                                  +
6821                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6822                                                 )
6823                                                 /
6824                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6825                                           );
6826
6827                                 // randomization for the blur value to combat persistent ghosting
6828                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6829                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6830
6831                                 // apply the blur
6832                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6833                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6834                                 {
6835                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6836                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6837                                         switch(vid.renderpath)
6838                                         {
6839                                         case RENDERPATH_GL11:
6840                                         case RENDERPATH_GL13:
6841                                         case RENDERPATH_GL20:
6842                                         case RENDERPATH_GLES1:
6843                                         case RENDERPATH_GLES2:
6844                                         case RENDERPATH_SOFT:
6845                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6846                                                 break;
6847                                         case RENDERPATH_D3D9:
6848                                         case RENDERPATH_D3D10:
6849                                         case RENDERPATH_D3D11:
6850                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6851                                                 break;
6852                                         }
6853                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6854                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6855                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6856                                 }
6857
6858                                 // updates old view angles for next pass
6859                                 VectorCopy(cl.viewangles, blur_oldangles);
6860
6861                                 // copy view into the ghost texture
6862                                 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);
6863                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6864                                 r_fb.ghosttexture_valid = true;
6865                         }
6866                 }
6867                 else
6868                 {
6869                         // no r_fb.colortexture means we're rendering to the real fb
6870                         // we may still have to do view tint...
6871                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6872                         {
6873                                 // apply a color tint to the whole view
6874                                 R_ResetViewRendering2D(0, NULL, NULL);
6875                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6876                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6877                                 R_SetupShader_Generic_NoTexture(false, true);
6878                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6879                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6880                         }
6881                         break; // no screen processing, no bloom, skip it
6882                 }
6883
6884                 if (r_fb.bloomtexture[0])
6885                 {
6886                         // make the bloom texture
6887                         R_Bloom_MakeTexture();
6888                 }
6889
6890 #if _MSC_VER >= 1400
6891 #define sscanf sscanf_s
6892 #endif
6893                 memset(uservecs, 0, sizeof(uservecs));
6894                 if (r_glsl_postprocess_uservec1_enable.integer)
6895                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6896                 if (r_glsl_postprocess_uservec2_enable.integer)
6897                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6898                 if (r_glsl_postprocess_uservec3_enable.integer)
6899                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6900                 if (r_glsl_postprocess_uservec4_enable.integer)
6901                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6902
6903                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6904                 GL_Color(1, 1, 1, 1);
6905                 GL_BlendFunc(GL_ONE, GL_ZERO);
6906
6907                 switch(vid.renderpath)
6908                 {
6909                 case RENDERPATH_GL20:
6910                 case RENDERPATH_GLES2:
6911                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6912                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6913                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6914                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6915                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6916                         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]);
6917                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6918                         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]);
6919                         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]);
6920                         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]);
6921                         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]);
6922                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6923                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6924                         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);
6925                         break;
6926                 case RENDERPATH_D3D9:
6927 #ifdef SUPPORTD3D
6928                         // 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...
6929                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6930                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6931                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6932                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6933                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6934                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6935                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6936                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6937                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6938                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6939                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6940                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6941                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6942                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6943 #endif
6944                         break;
6945                 case RENDERPATH_D3D10:
6946                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6947                         break;
6948                 case RENDERPATH_D3D11:
6949                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6950                         break;
6951                 case RENDERPATH_SOFT:
6952                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6953                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6954                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6955                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6956                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6957                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6958                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6959                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6960                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6961                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6962                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6963                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6964                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6965                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6966                         break;
6967                 default:
6968                         break;
6969                 }
6970                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6971                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6972                 break;
6973         case RENDERPATH_GL11:
6974         case RENDERPATH_GL13:
6975         case RENDERPATH_GLES1:
6976                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6977                 {
6978                         // apply a color tint to the whole view
6979                         R_ResetViewRendering2D(0, NULL, NULL);
6980                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6981                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6982                         R_SetupShader_Generic_NoTexture(false, true);
6983                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6984                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6985                 }
6986                 break;
6987         }
6988 }
6989
6990 matrix4x4_t r_waterscrollmatrix;
6991
6992 void R_UpdateFog(void)
6993 {
6994         // Nehahra fog
6995         if (gamemode == GAME_NEHAHRA)
6996         {
6997                 if (gl_fogenable.integer)
6998                 {
6999                         r_refdef.oldgl_fogenable = true;
7000                         r_refdef.fog_density = gl_fogdensity.value;
7001                         r_refdef.fog_red = gl_fogred.value;
7002                         r_refdef.fog_green = gl_foggreen.value;
7003                         r_refdef.fog_blue = gl_fogblue.value;
7004                         r_refdef.fog_alpha = 1;
7005                         r_refdef.fog_start = 0;
7006                         r_refdef.fog_end = gl_skyclip.value;
7007                         r_refdef.fog_height = 1<<30;
7008                         r_refdef.fog_fadedepth = 128;
7009                 }
7010                 else if (r_refdef.oldgl_fogenable)
7011                 {
7012                         r_refdef.oldgl_fogenable = false;
7013                         r_refdef.fog_density = 0;
7014                         r_refdef.fog_red = 0;
7015                         r_refdef.fog_green = 0;
7016                         r_refdef.fog_blue = 0;
7017                         r_refdef.fog_alpha = 0;
7018                         r_refdef.fog_start = 0;
7019                         r_refdef.fog_end = 0;
7020                         r_refdef.fog_height = 1<<30;
7021                         r_refdef.fog_fadedepth = 128;
7022                 }
7023         }
7024
7025         // fog parms
7026         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7027         r_refdef.fog_start = max(0, r_refdef.fog_start);
7028         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7029
7030         if (r_refdef.fog_density && r_drawfog.integer)
7031         {
7032                 r_refdef.fogenabled = true;
7033                 // this is the point where the fog reaches 0.9986 alpha, which we
7034                 // consider a good enough cutoff point for the texture
7035                 // (0.9986 * 256 == 255.6)
7036                 if (r_fog_exp2.integer)
7037                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7038                 else
7039                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7040                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7041                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7042                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7043                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7044                         R_BuildFogHeightTexture();
7045                 // fog color was already set
7046                 // update the fog texture
7047                 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)
7048                         R_BuildFogTexture();
7049                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7050                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7051         }
7052         else
7053                 r_refdef.fogenabled = false;
7054
7055         // fog color
7056         if (r_refdef.fog_density)
7057         {
7058                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7059                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7060                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7061
7062                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7063                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7064                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7065                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7066
7067                 {
7068                         vec3_t fogvec;
7069                         VectorCopy(r_refdef.fogcolor, fogvec);
7070                         //   color.rgb *= ContrastBoost * SceneBrightness;
7071                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7072                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7073                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7074                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7075                 }
7076         }
7077 }
7078
7079 void R_UpdateVariables(void)
7080 {
7081         R_Textures_Frame();
7082
7083         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7084
7085         r_refdef.farclip = r_farclip_base.value;
7086         if (r_refdef.scene.worldmodel)
7087                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7088         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7089
7090         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7091                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7092         r_refdef.polygonfactor = 0;
7093         r_refdef.polygonoffset = 0;
7094         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7095         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7096
7097         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7098         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7099         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7100         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7101         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7102         if (FAKELIGHT_ENABLED)
7103         {
7104                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7105         }
7106         else if (r_refdef.scene.worldmodel)
7107         {
7108                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7109         }
7110         if (r_showsurfaces.integer)
7111         {
7112                 r_refdef.scene.rtworld = false;
7113                 r_refdef.scene.rtworldshadows = false;
7114                 r_refdef.scene.rtdlight = false;
7115                 r_refdef.scene.rtdlightshadows = false;
7116                 r_refdef.lightmapintensity = 0;
7117         }
7118
7119         r_gpuskeletal = false;
7120         switch(vid.renderpath)
7121         {
7122         case RENDERPATH_GL20:
7123                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7124         case RENDERPATH_D3D9:
7125         case RENDERPATH_D3D10:
7126         case RENDERPATH_D3D11:
7127         case RENDERPATH_SOFT:
7128         case RENDERPATH_GLES2:
7129                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7130                 {
7131                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7132                         {
7133                                 // build GLSL gamma texture
7134 #define RAMPWIDTH 256
7135                                 unsigned short ramp[RAMPWIDTH * 3];
7136                                 unsigned char rampbgr[RAMPWIDTH][4];
7137                                 int i;
7138
7139                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7140
7141                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7142                                 for(i = 0; i < RAMPWIDTH; ++i)
7143                                 {
7144                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7145                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7146                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7147                                         rampbgr[i][3] = 0;
7148                                 }
7149                                 if (r_texture_gammaramps)
7150                                 {
7151                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7152                                 }
7153                                 else
7154                                 {
7155                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7156                                 }
7157                         }
7158                 }
7159                 else
7160                 {
7161                         // remove GLSL gamma texture
7162                 }
7163                 break;
7164         case RENDERPATH_GL11:
7165         case RENDERPATH_GL13:
7166         case RENDERPATH_GLES1:
7167                 break;
7168         }
7169 }
7170
7171 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7172 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7173 /*
7174 ================
7175 R_SelectScene
7176 ================
7177 */
7178 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7179         if( scenetype != r_currentscenetype ) {
7180                 // store the old scenetype
7181                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7182                 r_currentscenetype = scenetype;
7183                 // move in the new scene
7184                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7185         }
7186 }
7187
7188 /*
7189 ================
7190 R_GetScenePointer
7191 ================
7192 */
7193 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7194 {
7195         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7196         if( scenetype == r_currentscenetype ) {
7197                 return &r_refdef.scene;
7198         } else {
7199                 return &r_scenes_store[ scenetype ];
7200         }
7201 }
7202
7203 static int R_SortEntities_Compare(const void *ap, const void *bp)
7204 {
7205         const entity_render_t *a = *(const entity_render_t **)ap;
7206         const entity_render_t *b = *(const entity_render_t **)bp;
7207
7208         // 1. compare model
7209         if(a->model < b->model)
7210                 return -1;
7211         if(a->model > b->model)
7212                 return +1;
7213
7214         // 2. compare skin
7215         // TODO possibly calculate the REAL skinnum here first using
7216         // skinscenes?
7217         if(a->skinnum < b->skinnum)
7218                 return -1;
7219         if(a->skinnum > b->skinnum)
7220                 return +1;
7221
7222         // everything we compared is equal
7223         return 0;
7224 }
7225 static void R_SortEntities(void)
7226 {
7227         // below or equal 2 ents, sorting never gains anything
7228         if(r_refdef.scene.numentities <= 2)
7229                 return;
7230         // sort
7231         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7232 }
7233
7234 /*
7235 ================
7236 R_RenderView
7237 ================
7238 */
7239 int dpsoftrast_test;
7240 extern cvar_t r_shadow_bouncegrid;
7241 void R_RenderView(void)
7242 {
7243         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7244         int fbo;
7245         rtexture_t *depthtexture;
7246         rtexture_t *colortexture;
7247
7248         dpsoftrast_test = r_test.integer;
7249
7250         if (r_timereport_active)
7251                 R_TimeReport("start");
7252         r_textureframe++; // used only by R_GetCurrentTexture
7253         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7254
7255         if(R_CompileShader_CheckStaticParms())
7256                 R_GLSL_Restart_f();
7257
7258         if (!r_drawentities.integer)
7259                 r_refdef.scene.numentities = 0;
7260         else if (r_sortentities.integer)
7261                 R_SortEntities();
7262
7263         R_AnimCache_ClearCache();
7264
7265         /* adjust for stereo display */
7266         if(R_Stereo_Active())
7267         {
7268                 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);
7269                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7270         }
7271
7272         if (r_refdef.view.isoverlay)
7273         {
7274                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7275                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7276                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7277                 R_TimeReport("depthclear");
7278
7279                 r_refdef.view.showdebug = false;
7280
7281                 r_fb.water.enabled = false;
7282                 r_fb.water.numwaterplanes = 0;
7283
7284                 R_RenderScene(0, NULL, NULL);
7285
7286                 r_refdef.view.matrix = originalmatrix;
7287
7288                 CHECKGLERROR
7289                 return;
7290         }
7291
7292         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7293         {
7294                 r_refdef.view.matrix = originalmatrix;
7295                 return;
7296         }
7297
7298         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7299
7300         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7301                 // in sRGB fallback, behave similar to true sRGB: convert this
7302                 // value from linear to sRGB
7303                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7304
7305         R_RenderView_UpdateViewVectors();
7306
7307         R_Shadow_UpdateWorldLightSelection();
7308
7309         R_Bloom_StartFrame();
7310
7311         // apply bloom brightness offset
7312         if(r_fb.bloomtexture[0])
7313                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7314
7315         R_Water_StartFrame();
7316
7317         // now we probably have an fbo to render into
7318         fbo = r_fb.fbo;
7319         depthtexture = r_fb.depthtexture;
7320         colortexture = r_fb.colortexture;
7321
7322         CHECKGLERROR
7323         if (r_timereport_active)
7324                 R_TimeReport("viewsetup");
7325
7326         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7327
7328         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7329         {
7330                 R_ClearScreen(r_refdef.fogenabled);
7331                 if (r_timereport_active)
7332                         R_TimeReport("viewclear");
7333         }
7334         r_refdef.view.clear = true;
7335
7336         r_refdef.view.showdebug = true;
7337
7338         R_View_Update();
7339         if (r_timereport_active)
7340                 R_TimeReport("visibility");
7341
7342         R_AnimCache_CacheVisibleEntities();
7343         if (r_timereport_active)
7344                 R_TimeReport("animcache");
7345
7346         R_Shadow_UpdateBounceGridTexture();
7347         if (r_timereport_active && r_shadow_bouncegrid.integer)
7348                 R_TimeReport("bouncegrid");
7349
7350         r_fb.water.numwaterplanes = 0;
7351         if (r_fb.water.enabled)
7352                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7353
7354         R_RenderScene(fbo, depthtexture, colortexture);
7355         r_fb.water.numwaterplanes = 0;
7356
7357         R_BlendView(fbo, depthtexture, colortexture);
7358         if (r_timereport_active)
7359                 R_TimeReport("blendview");
7360
7361         GL_Scissor(0, 0, vid.width, vid.height);
7362         GL_ScissorTest(false);
7363
7364         r_refdef.view.matrix = originalmatrix;
7365
7366         CHECKGLERROR
7367 }
7368
7369 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7370 {
7371         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7372         {
7373                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7374                 if (r_timereport_active)
7375                         R_TimeReport("waterworld");
7376         }
7377
7378         // don't let sound skip if going slow
7379         if (r_refdef.scene.extraupdate)
7380                 S_ExtraUpdate ();
7381
7382         R_DrawModelsAddWaterPlanes();
7383         if (r_timereport_active)
7384                 R_TimeReport("watermodels");
7385
7386         if (r_fb.water.numwaterplanes)
7387         {
7388                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7389                 if (r_timereport_active)
7390                         R_TimeReport("waterscenes");
7391         }
7392 }
7393
7394 extern cvar_t cl_locs_show;
7395 static void R_DrawLocs(void);
7396 static void R_DrawEntityBBoxes(void);
7397 static void R_DrawModelDecals(void);
7398 extern cvar_t cl_decals_newsystem;
7399 extern qboolean r_shadow_usingdeferredprepass;
7400 extern int r_shadow_shadowmapatlas_modelshadows_size;
7401 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7402 {
7403         qboolean shadowmapping = false;
7404
7405         if (r_timereport_active)
7406                 R_TimeReport("beginscene");
7407
7408         r_refdef.stats[r_stat_renders]++;
7409
7410         R_UpdateFog();
7411
7412         // don't let sound skip if going slow
7413         if (r_refdef.scene.extraupdate)
7414                 S_ExtraUpdate ();
7415
7416         R_MeshQueue_BeginScene();
7417
7418         R_SkyStartFrame();
7419
7420         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);
7421
7422         if (r_timereport_active)
7423                 R_TimeReport("skystartframe");
7424
7425         if (cl.csqc_vidvars.drawworld)
7426         {
7427                 // don't let sound skip if going slow
7428                 if (r_refdef.scene.extraupdate)
7429                         S_ExtraUpdate ();
7430
7431                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7432                 {
7433                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7434                         if (r_timereport_active)
7435                                 R_TimeReport("worldsky");
7436                 }
7437
7438                 if (R_DrawBrushModelsSky() && r_timereport_active)
7439                         R_TimeReport("bmodelsky");
7440
7441                 if (skyrendermasked && skyrenderlater)
7442                 {
7443                         // we have to force off the water clipping plane while rendering sky
7444                         R_SetupView(false, fbo, depthtexture, colortexture);
7445                         R_Sky();
7446                         R_SetupView(true, fbo, depthtexture, colortexture);
7447                         if (r_timereport_active)
7448                                 R_TimeReport("sky");
7449                 }
7450         }
7451
7452         R_Shadow_PrepareModelShadows();
7453         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7454         if (r_timereport_active)
7455                 R_TimeReport("preparelights");
7456
7457         // render all the shadowmaps that will be used for this view
7458         shadowmapping = R_Shadow_ShadowMappingEnabled();
7459         if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7460         {
7461                 R_Shadow_DrawShadowMaps();
7462                 if (r_timereport_active)
7463                         R_TimeReport("shadowmaps");
7464         }
7465
7466         // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7467         if (r_shadow_usingdeferredprepass)
7468                 R_Shadow_DrawPrepass();
7469
7470         // now we begin the forward pass of the view render
7471         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7472         {
7473                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7474                 if (r_timereport_active)
7475                         R_TimeReport("worlddepth");
7476         }
7477         if (r_depthfirst.integer >= 2)
7478         {
7479                 R_DrawModelsDepth();
7480                 if (r_timereport_active)
7481                         R_TimeReport("modeldepth");
7482         }
7483
7484         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7485         {
7486                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7487                 if (r_timereport_active)
7488                         R_TimeReport("world");
7489         }
7490
7491         // don't let sound skip if going slow
7492         if (r_refdef.scene.extraupdate)
7493                 S_ExtraUpdate ();
7494
7495         R_DrawModels();
7496         if (r_timereport_active)
7497                 R_TimeReport("models");
7498
7499         // don't let sound skip if going slow
7500         if (r_refdef.scene.extraupdate)
7501                 S_ExtraUpdate ();
7502
7503         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7504         {
7505                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7506                 R_Shadow_DrawModelShadows();
7507                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7508                 // don't let sound skip if going slow
7509                 if (r_refdef.scene.extraupdate)
7510                         S_ExtraUpdate ();
7511         }
7512
7513         if (!r_shadow_usingdeferredprepass)
7514         {
7515                 R_Shadow_DrawLights();
7516                 if (r_timereport_active)
7517                         R_TimeReport("rtlights");
7518         }
7519
7520         // don't let sound skip if going slow
7521         if (r_refdef.scene.extraupdate)
7522                 S_ExtraUpdate ();
7523
7524         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7525         {
7526                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7527                 R_Shadow_DrawModelShadows();
7528                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7529                 // don't let sound skip if going slow
7530                 if (r_refdef.scene.extraupdate)
7531                         S_ExtraUpdate ();
7532         }
7533
7534         if (cl.csqc_vidvars.drawworld)
7535         {
7536                 if (cl_decals_newsystem.integer)
7537                 {
7538                         R_DrawModelDecals();
7539                         if (r_timereport_active)
7540                                 R_TimeReport("modeldecals");
7541                 }
7542                 else
7543                 {
7544                         R_DrawDecals();
7545                         if (r_timereport_active)
7546                                 R_TimeReport("decals");
7547                 }
7548
7549                 R_DrawParticles();
7550                 if (r_timereport_active)
7551                         R_TimeReport("particles");
7552
7553                 R_DrawExplosions();
7554                 if (r_timereport_active)
7555                         R_TimeReport("explosions");
7556
7557                 R_DrawLightningBeams();
7558                 if (r_timereport_active)
7559                         R_TimeReport("lightning");
7560         }
7561
7562         if (cl.csqc_loaded)
7563                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7564
7565         if (r_refdef.view.showdebug)
7566         {
7567                 if (cl_locs_show.integer)
7568                 {
7569                         R_DrawLocs();
7570                         if (r_timereport_active)
7571                                 R_TimeReport("showlocs");
7572                 }
7573
7574                 if (r_drawportals.integer)
7575                 {
7576                         R_DrawPortals();
7577                         if (r_timereport_active)
7578                                 R_TimeReport("portals");
7579                 }
7580
7581                 if (r_showbboxes.value > 0)
7582                 {
7583                         R_DrawEntityBBoxes();
7584                         if (r_timereport_active)
7585                                 R_TimeReport("bboxes");
7586                 }
7587         }
7588
7589         if (r_transparent.integer)
7590         {
7591                 R_MeshQueue_RenderTransparent();
7592                 if (r_timereport_active)
7593                         R_TimeReport("drawtrans");
7594         }
7595
7596         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))
7597         {
7598                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7599                 if (r_timereport_active)
7600                         R_TimeReport("worlddebug");
7601                 R_DrawModelsDebug();
7602                 if (r_timereport_active)
7603                         R_TimeReport("modeldebug");
7604         }
7605
7606         if (cl.csqc_vidvars.drawworld)
7607         {
7608                 R_Shadow_DrawCoronas();
7609                 if (r_timereport_active)
7610                         R_TimeReport("coronas");
7611         }
7612
7613 #if 0
7614         {
7615                 GL_DepthTest(false);
7616                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7617                 GL_Color(1, 1, 1, 1);
7618                 qglBegin(GL_POLYGON);
7619                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7620                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7621                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7622                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7623                 qglEnd();
7624                 qglBegin(GL_POLYGON);
7625                 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]);
7626                 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]);
7627                 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]);
7628                 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]);
7629                 qglEnd();
7630                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7631         }
7632 #endif
7633
7634         // don't let sound skip if going slow
7635         if (r_refdef.scene.extraupdate)
7636                 S_ExtraUpdate ();
7637 }
7638
7639 static const unsigned short bboxelements[36] =
7640 {
7641         5, 1, 3, 5, 3, 7,
7642         6, 2, 0, 6, 0, 4,
7643         7, 3, 2, 7, 2, 6,
7644         4, 0, 1, 4, 1, 5,
7645         4, 5, 7, 4, 7, 6,
7646         1, 0, 2, 1, 2, 3,
7647 };
7648
7649 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7650 {
7651         int i;
7652         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7653
7654         RSurf_ActiveWorldEntity();
7655
7656         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7657         GL_DepthMask(false);
7658         GL_DepthRange(0, 1);
7659         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7660 //      R_Mesh_ResetTextureState();
7661
7662         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7663         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7664         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7665         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7666         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7667         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7668         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7669         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7670         R_FillColors(color4f, 8, cr, cg, cb, ca);
7671         if (r_refdef.fogenabled)
7672         {
7673                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7674                 {
7675                         f1 = RSurf_FogVertex(v);
7676                         f2 = 1 - f1;
7677                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7678                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7679                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7680                 }
7681         }
7682         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7683         R_Mesh_ResetTextureState();
7684         R_SetupShader_Generic_NoTexture(false, false);
7685         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7686 }
7687
7688 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7689 {
7690         prvm_prog_t *prog = SVVM_prog;
7691         int i;
7692         float color[4];
7693         prvm_edict_t *edict;
7694
7695         // this function draws bounding boxes of server entities
7696         if (!sv.active)
7697                 return;
7698
7699         GL_CullFace(GL_NONE);
7700         R_SetupShader_Generic_NoTexture(false, false);
7701
7702         for (i = 0;i < numsurfaces;i++)
7703         {
7704                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7705                 switch ((int)PRVM_serveredictfloat(edict, solid))
7706                 {
7707                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7708                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7709                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7710                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7711                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7712                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7713                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7714                 }
7715                 color[3] *= r_showbboxes.value;
7716                 color[3] = bound(0, color[3], 1);
7717                 GL_DepthTest(!r_showdisabledepthtest.integer);
7718                 GL_CullFace(r_refdef.view.cullface_front);
7719                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7720         }
7721 }
7722
7723 static void R_DrawEntityBBoxes(void)
7724 {
7725         int i;
7726         prvm_edict_t *edict;
7727         vec3_t center;
7728         prvm_prog_t *prog = SVVM_prog;
7729
7730         // this function draws bounding boxes of server entities
7731         if (!sv.active)
7732                 return;
7733
7734         for (i = 0;i < prog->num_edicts;i++)
7735         {
7736                 edict = PRVM_EDICT_NUM(i);
7737                 if (edict->priv.server->free)
7738                         continue;
7739                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7740                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7741                         continue;
7742                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7743                         continue;
7744                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7745                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7746         }
7747 }
7748
7749 static const int nomodelelement3i[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 unsigned short nomodelelement3s[24] =
7762 {
7763         5, 2, 0,
7764         5, 1, 2,
7765         5, 0, 3,
7766         5, 3, 1,
7767         0, 2, 4,
7768         2, 1, 4,
7769         3, 0, 4,
7770         1, 3, 4
7771 };
7772
7773 static const float nomodelvertex3f[6*3] =
7774 {
7775         -16,   0,   0,
7776          16,   0,   0,
7777           0, -16,   0,
7778           0,  16,   0,
7779           0,   0, -16,
7780           0,   0,  16
7781 };
7782
7783 static const float nomodelcolor4f[6*4] =
7784 {
7785         0.0f, 0.0f, 0.5f, 1.0f,
7786         0.0f, 0.0f, 0.5f, 1.0f,
7787         0.0f, 0.5f, 0.0f, 1.0f,
7788         0.0f, 0.5f, 0.0f, 1.0f,
7789         0.5f, 0.0f, 0.0f, 1.0f,
7790         0.5f, 0.0f, 0.0f, 1.0f
7791 };
7792
7793 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7794 {
7795         int i;
7796         float f1, f2, *c;
7797         float color4f[6*4];
7798
7799         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);
7800
7801         // this is only called once per entity so numsurfaces is always 1, and
7802         // surfacelist is always {0}, so this code does not handle batches
7803
7804         if (rsurface.ent_flags & RENDER_ADDITIVE)
7805         {
7806                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7807                 GL_DepthMask(false);
7808         }
7809         else if (rsurface.colormod[3] < 1)
7810         {
7811                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7812                 GL_DepthMask(false);
7813         }
7814         else
7815         {
7816                 GL_BlendFunc(GL_ONE, GL_ZERO);
7817                 GL_DepthMask(true);
7818         }
7819         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7820         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7821         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7822         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7823         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7824         for (i = 0, c = color4f;i < 6;i++, c += 4)
7825         {
7826                 c[0] *= rsurface.colormod[0];
7827                 c[1] *= rsurface.colormod[1];
7828                 c[2] *= rsurface.colormod[2];
7829                 c[3] *= rsurface.colormod[3];
7830         }
7831         if (r_refdef.fogenabled)
7832         {
7833                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7834                 {
7835                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7836                         f2 = 1 - f1;
7837                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7838                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7839                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7840                 }
7841         }
7842 //      R_Mesh_ResetTextureState();
7843         R_SetupShader_Generic_NoTexture(false, false);
7844         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7845         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7846 }
7847
7848 void R_DrawNoModel(entity_render_t *ent)
7849 {
7850         vec3_t org;
7851         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7852         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7853                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7854         else
7855                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7856 }
7857
7858 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7859 {
7860         vec3_t right1, right2, diff, normal;
7861
7862         VectorSubtract (org2, org1, normal);
7863
7864         // calculate 'right' vector for start
7865         VectorSubtract (r_refdef.view.origin, org1, diff);
7866         CrossProduct (normal, diff, right1);
7867         VectorNormalize (right1);
7868
7869         // calculate 'right' vector for end
7870         VectorSubtract (r_refdef.view.origin, org2, diff);
7871         CrossProduct (normal, diff, right2);
7872         VectorNormalize (right2);
7873
7874         vert[ 0] = org1[0] + width * right1[0];
7875         vert[ 1] = org1[1] + width * right1[1];
7876         vert[ 2] = org1[2] + width * right1[2];
7877         vert[ 3] = org1[0] - width * right1[0];
7878         vert[ 4] = org1[1] - width * right1[1];
7879         vert[ 5] = org1[2] - width * right1[2];
7880         vert[ 6] = org2[0] - width * right2[0];
7881         vert[ 7] = org2[1] - width * right2[1];
7882         vert[ 8] = org2[2] - width * right2[2];
7883         vert[ 9] = org2[0] + width * right2[0];
7884         vert[10] = org2[1] + width * right2[1];
7885         vert[11] = org2[2] + width * right2[2];
7886 }
7887
7888 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)
7889 {
7890         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7891         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7892         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7893         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7894         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7895         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7896         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7897         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7898         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7899         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7900         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7901         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7902 }
7903
7904 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7905 {
7906         int i;
7907         float *vertex3f;
7908         float v[3];
7909         VectorSet(v, x, y, z);
7910         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7911                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7912                         break;
7913         if (i == mesh->numvertices)
7914         {
7915                 if (mesh->numvertices < mesh->maxvertices)
7916                 {
7917                         VectorCopy(v, vertex3f);
7918                         mesh->numvertices++;
7919                 }
7920                 return mesh->numvertices;
7921         }
7922         else
7923                 return i;
7924 }
7925
7926 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7927 {
7928         int i;
7929         int *e, element[3];
7930         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7931         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7932         e = mesh->element3i + mesh->numtriangles * 3;
7933         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7934         {
7935                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7936                 if (mesh->numtriangles < mesh->maxtriangles)
7937                 {
7938                         *e++ = element[0];
7939                         *e++ = element[1];
7940                         *e++ = element[2];
7941                         mesh->numtriangles++;
7942                 }
7943                 element[1] = element[2];
7944         }
7945 }
7946
7947 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7948 {
7949         int i;
7950         int *e, element[3];
7951         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7952         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7953         e = mesh->element3i + mesh->numtriangles * 3;
7954         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7955         {
7956                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7957                 if (mesh->numtriangles < mesh->maxtriangles)
7958                 {
7959                         *e++ = element[0];
7960                         *e++ = element[1];
7961                         *e++ = element[2];
7962                         mesh->numtriangles++;
7963                 }
7964                 element[1] = element[2];
7965         }
7966 }
7967
7968 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7969 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7970 {
7971         int planenum, planenum2;
7972         int w;
7973         int tempnumpoints;
7974         mplane_t *plane, *plane2;
7975         double maxdist;
7976         double temppoints[2][256*3];
7977         // figure out how large a bounding box we need to properly compute this brush
7978         maxdist = 0;
7979         for (w = 0;w < numplanes;w++)
7980                 maxdist = max(maxdist, fabs(planes[w].dist));
7981         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7982         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7983         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7984         {
7985                 w = 0;
7986                 tempnumpoints = 4;
7987                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7988                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7989                 {
7990                         if (planenum2 == planenum)
7991                                 continue;
7992                         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);
7993                         w = !w;
7994                 }
7995                 if (tempnumpoints < 3)
7996                         continue;
7997                 // generate elements forming a triangle fan for this polygon
7998                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7999         }
8000 }
8001
8002 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)
8003 {
8004         texturelayer_t *layer;
8005         layer = t->currentlayers + t->currentnumlayers++;
8006         layer->type = type;
8007         layer->depthmask = depthmask;
8008         layer->blendfunc1 = blendfunc1;
8009         layer->blendfunc2 = blendfunc2;
8010         layer->texture = texture;
8011         layer->texmatrix = *matrix;
8012         layer->color[0] = r;
8013         layer->color[1] = g;
8014         layer->color[2] = b;
8015         layer->color[3] = a;
8016 }
8017
8018 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8019 {
8020         if(parms[0] == 0 && parms[1] == 0)
8021                 return false;
8022         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8023                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8024                         return false;
8025         return true;
8026 }
8027
8028 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8029 {
8030         double index, f;
8031         index = parms[2] + rsurface.shadertime * parms[3];
8032         index -= floor(index);
8033         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8034         {
8035         default:
8036         case Q3WAVEFUNC_NONE:
8037         case Q3WAVEFUNC_NOISE:
8038         case Q3WAVEFUNC_COUNT:
8039                 f = 0;
8040                 break;
8041         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8042         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8043         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8044         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8045         case Q3WAVEFUNC_TRIANGLE:
8046                 index *= 4;
8047                 f = index - floor(index);
8048                 if (index < 1)
8049                 {
8050                         // f = f;
8051                 }
8052                 else if (index < 2)
8053                         f = 1 - f;
8054                 else if (index < 3)
8055                         f = -f;
8056                 else
8057                         f = -(1 - f);
8058                 break;
8059         }
8060         f = parms[0] + parms[1] * f;
8061         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8062                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8063         return (float) f;
8064 }
8065
8066 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8067 {
8068         int w, h, idx;
8069         float shadertime;
8070         float f;
8071         float offsetd[2];
8072         float tcmat[12];
8073         matrix4x4_t matrix, temp;
8074         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8075         // it's better to have one huge fixup every 9 hours than gradual
8076         // degradation over time which looks consistently bad after many hours.
8077         //
8078         // tcmod scroll in particular suffers from this degradation which can't be
8079         // effectively worked around even with floor() tricks because we don't
8080         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8081         // a workaround involving floor() would be incorrect anyway...
8082         shadertime = rsurface.shadertime;
8083         if (shadertime >= 32768.0f)
8084                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8085         switch(tcmod->tcmod)
8086         {
8087                 case Q3TCMOD_COUNT:
8088                 case Q3TCMOD_NONE:
8089                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8090                                 matrix = r_waterscrollmatrix;
8091                         else
8092                                 matrix = identitymatrix;
8093                         break;
8094                 case Q3TCMOD_ENTITYTRANSLATE:
8095                         // this is used in Q3 to allow the gamecode to control texcoord
8096                         // scrolling on the entity, which is not supported in darkplaces yet.
8097                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8098                         break;
8099                 case Q3TCMOD_ROTATE:
8100                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8101                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8102                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8103                         break;
8104                 case Q3TCMOD_SCALE:
8105                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8106                         break;
8107                 case Q3TCMOD_SCROLL:
8108                         // this particular tcmod is a "bug for bug" compatible one with regards to
8109                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8110                         // specifically did the wrapping and so we must mimic that...
8111                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8112                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8113                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8114                         break;
8115                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8116                         w = (int) tcmod->parms[0];
8117                         h = (int) tcmod->parms[1];
8118                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8119                         f = f - floor(f);
8120                         idx = (int) floor(f * w * h);
8121                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8122                         break;
8123                 case Q3TCMOD_STRETCH:
8124                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8125                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8126                         break;
8127                 case Q3TCMOD_TRANSFORM:
8128                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8129                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8130                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8131                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8132                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8133                         break;
8134                 case Q3TCMOD_TURBULENT:
8135                         // this is handled in the RSurf_PrepareVertices function
8136                         matrix = identitymatrix;
8137                         break;
8138         }
8139         temp = *texmatrix;
8140         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8141 }
8142
8143 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8144 {
8145         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8146         char name[MAX_QPATH];
8147         skinframe_t *skinframe;
8148         unsigned char pixels[296*194];
8149         strlcpy(cache->name, skinname, sizeof(cache->name));
8150         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8151         if (developer_loading.integer)
8152                 Con_Printf("loading %s\n", name);
8153         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8154         if (!skinframe || !skinframe->base)
8155         {
8156                 unsigned char *f;
8157                 fs_offset_t filesize;
8158                 skinframe = NULL;
8159                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8160                 if (f)
8161                 {
8162                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8163                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8164                         Mem_Free(f);
8165                 }
8166         }
8167         cache->skinframe = skinframe;
8168 }
8169
8170 texture_t *R_GetCurrentTexture(texture_t *t)
8171 {
8172         int i;
8173         const entity_render_t *ent = rsurface.entity;
8174         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8175         q3shaderinfo_layer_tcmod_t *tcmod;
8176
8177         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8178                 return t->currentframe;
8179         t->update_lastrenderframe = r_textureframe;
8180         t->update_lastrenderentity = (void *)ent;
8181
8182         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8183                 t->camera_entity = ent->entitynumber;
8184         else
8185                 t->camera_entity = 0;
8186
8187         // switch to an alternate material if this is a q1bsp animated material
8188         {
8189                 texture_t *texture = t;
8190                 int s = rsurface.ent_skinnum;
8191                 if ((unsigned int)s >= (unsigned int)model->numskins)
8192                         s = 0;
8193                 if (model->skinscenes)
8194                 {
8195                         if (model->skinscenes[s].framecount > 1)
8196                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8197                         else
8198                                 s = model->skinscenes[s].firstframe;
8199                 }
8200                 if (s > 0)
8201                         t = t + s * model->num_surfaces;
8202                 if (t->animated)
8203                 {
8204                         // use an alternate animation if the entity's frame is not 0,
8205                         // and only if the texture has an alternate animation
8206                         if (t->animated == 2) // q2bsp
8207                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8208                         else if (rsurface.ent_alttextures && t->anim_total[1])
8209                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8210                         else
8211                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8212                 }
8213                 texture->currentframe = t;
8214         }
8215
8216         // update currentskinframe to be a qw skin or animation frame
8217         if (rsurface.ent_qwskin >= 0)
8218         {
8219                 i = rsurface.ent_qwskin;
8220                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8221                 {
8222                         r_qwskincache_size = cl.maxclients;
8223                         if (r_qwskincache)
8224                                 Mem_Free(r_qwskincache);
8225                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8226                 }
8227                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8228                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8229                 t->currentskinframe = r_qwskincache[i].skinframe;
8230                 if (t->currentskinframe == NULL)
8231                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8232         }
8233         else if (t->numskinframes >= 2)
8234                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8235         if (t->backgroundnumskinframes >= 2)
8236                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8237
8238         t->currentmaterialflags = t->basematerialflags;
8239         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8240         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8241                 t->currentalpha *= r_wateralpha.value;
8242         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8243                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8244         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8245                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8246         if (!(rsurface.ent_flags & RENDER_LIGHT))
8247                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8248         else if (FAKELIGHT_ENABLED)
8249         {
8250                 // no modellight if using fakelight for the map
8251         }
8252         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8253         {
8254                 // pick a model lighting mode
8255                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8256                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8257                 else
8258                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8259         }
8260         if (rsurface.ent_flags & RENDER_ADDITIVE)
8261                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8262         else if (t->currentalpha < 1)
8263                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8264         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8265         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8266                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8267         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8268                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8269         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8270                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8271         if (t->backgroundnumskinframes)
8272                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8273         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8274         {
8275                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8276                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8277         }
8278         else
8279                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8280         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8281         {
8282                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8283                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8284         }
8285         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8286                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8287
8288         // there is no tcmod
8289         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8290         {
8291                 t->currenttexmatrix = r_waterscrollmatrix;
8292                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8293         }
8294         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8295         {
8296                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8297                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8298         }
8299
8300         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8301                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8302         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8303                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8304
8305         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8306         if (t->currentskinframe->qpixels)
8307                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8308         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8309         if (!t->basetexture)
8310                 t->basetexture = r_texture_notexture;
8311         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8312         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8313         t->nmaptexture = t->currentskinframe->nmap;
8314         if (!t->nmaptexture)
8315                 t->nmaptexture = r_texture_blanknormalmap;
8316         t->glosstexture = r_texture_black;
8317         t->glowtexture = t->currentskinframe->glow;
8318         t->fogtexture = t->currentskinframe->fog;
8319         t->reflectmasktexture = t->currentskinframe->reflect;
8320         if (t->backgroundnumskinframes)
8321         {
8322                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8323                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8324                 t->backgroundglosstexture = r_texture_black;
8325                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8326                 if (!t->backgroundnmaptexture)
8327                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8328                 // make sure that if glow is going to be used, both textures are not NULL
8329                 if (!t->backgroundglowtexture && t->glowtexture)
8330                         t->backgroundglowtexture = r_texture_black;
8331                 if (!t->glowtexture && t->backgroundglowtexture)
8332                         t->glowtexture = r_texture_black;
8333         }
8334         else
8335         {
8336                 t->backgroundbasetexture = r_texture_white;
8337                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8338                 t->backgroundglosstexture = r_texture_black;
8339                 t->backgroundglowtexture = NULL;
8340         }
8341         t->specularpower = r_shadow_glossexponent.value;
8342         // TODO: store reference values for these in the texture?
8343         t->specularscale = 0;
8344         if (r_shadow_gloss.integer > 0)
8345         {
8346                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8347                 {
8348                         if (r_shadow_glossintensity.value > 0)
8349                         {
8350                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8351                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8352                                 t->specularscale = r_shadow_glossintensity.value;
8353                         }
8354                 }
8355                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8356                 {
8357                         t->glosstexture = r_texture_white;
8358                         t->backgroundglosstexture = r_texture_white;
8359                         t->specularscale = r_shadow_gloss2intensity.value;
8360                         t->specularpower = r_shadow_gloss2exponent.value;
8361                 }
8362         }
8363         t->specularscale *= t->specularscalemod;
8364         t->specularpower *= t->specularpowermod;
8365         t->rtlightambient = 0;
8366
8367         // lightmaps mode looks bad with dlights using actual texturing, so turn
8368         // off the colormap and glossmap, but leave the normalmap on as it still
8369         // accurately represents the shading involved
8370         if (gl_lightmaps.integer)
8371         {
8372                 t->basetexture = r_texture_grey128;
8373                 t->pantstexture = r_texture_black;
8374                 t->shirttexture = r_texture_black;
8375                 if (gl_lightmaps.integer < 2)
8376                         t->nmaptexture = r_texture_blanknormalmap;
8377                 t->glosstexture = r_texture_black;
8378                 t->glowtexture = NULL;
8379                 t->fogtexture = NULL;
8380                 t->reflectmasktexture = NULL;
8381                 t->backgroundbasetexture = NULL;
8382                 if (gl_lightmaps.integer < 2)
8383                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8384                 t->backgroundglosstexture = r_texture_black;
8385                 t->backgroundglowtexture = NULL;
8386                 t->specularscale = 0;
8387                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8388         }
8389
8390         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8391         VectorClear(t->dlightcolor);
8392         t->currentnumlayers = 0;
8393         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8394         {
8395                 int blendfunc1, blendfunc2;
8396                 qboolean depthmask;
8397                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8398                 {
8399                         blendfunc1 = GL_SRC_ALPHA;
8400                         blendfunc2 = GL_ONE;
8401                 }
8402                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8403                 {
8404                         blendfunc1 = GL_SRC_ALPHA;
8405                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8406                 }
8407                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8408                 {
8409                         blendfunc1 = t->customblendfunc[0];
8410                         blendfunc2 = t->customblendfunc[1];
8411                 }
8412                 else
8413                 {
8414                         blendfunc1 = GL_ONE;
8415                         blendfunc2 = GL_ZERO;
8416                 }
8417                 // don't colormod evilblend textures
8418                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8419                         VectorSet(t->lightmapcolor, 1, 1, 1);
8420                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8421                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8422                 {
8423                         // fullbright is not affected by r_refdef.lightmapintensity
8424                         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]);
8425                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8426                                 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]);
8427                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8428                                 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]);
8429                 }
8430                 else
8431                 {
8432                         vec3_t ambientcolor;
8433                         float colorscale;
8434                         // set the color tint used for lights affecting this surface
8435                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8436                         colorscale = 2;
8437                         // q3bsp has no lightmap updates, so the lightstylevalue that
8438                         // would normally be baked into the lightmap must be
8439                         // applied to the color
8440                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8441                         if (model->type == mod_brushq3)
8442                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8443                         colorscale *= r_refdef.lightmapintensity;
8444                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8445                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8446                         // basic lit geometry
8447                         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]);
8448                         // add pants/shirt if needed
8449                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8450                                 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]);
8451                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8452                                 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]);
8453                         // now add ambient passes if needed
8454                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8455                         {
8456                                 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]);
8457                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8458                                         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]);
8459                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8460                                         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]);
8461                         }
8462                 }
8463                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8464                         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]);
8465                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8466                 {
8467                         // if this is opaque use alpha blend which will darken the earlier
8468                         // passes cheaply.
8469                         //
8470                         // if this is an alpha blended material, all the earlier passes
8471                         // were darkened by fog already, so we only need to add the fog
8472                         // color ontop through the fog mask texture
8473                         //
8474                         // if this is an additive blended material, all the earlier passes
8475                         // were darkened by fog already, and we should not add fog color
8476                         // (because the background was not darkened, there is no fog color
8477                         // that was lost behind it).
8478                         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]);
8479                 }
8480         }
8481
8482         return t;
8483 }
8484
8485 rsurfacestate_t rsurface;
8486
8487 void RSurf_ActiveWorldEntity(void)
8488 {
8489         dp_model_t *model = r_refdef.scene.worldmodel;
8490         //if (rsurface.entity == r_refdef.scene.worldentity)
8491         //      return;
8492         rsurface.entity = r_refdef.scene.worldentity;
8493         rsurface.skeleton = NULL;
8494         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8495         rsurface.ent_skinnum = 0;
8496         rsurface.ent_qwskin = -1;
8497         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8498         rsurface.shadertime = r_refdef.scene.time;
8499         rsurface.matrix = identitymatrix;
8500         rsurface.inversematrix = identitymatrix;
8501         rsurface.matrixscale = 1;
8502         rsurface.inversematrixscale = 1;
8503         R_EntityMatrix(&identitymatrix);
8504         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8505         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8506         rsurface.fograngerecip = r_refdef.fograngerecip;
8507         rsurface.fogheightfade = r_refdef.fogheightfade;
8508         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8509         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8510         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8511         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8512         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8513         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8514         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8515         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8516         rsurface.colormod[3] = 1;
8517         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);
8518         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8519         rsurface.frameblend[0].lerp = 1;
8520         rsurface.ent_alttextures = false;
8521         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8522         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8523         rsurface.entityskeletaltransform3x4 = NULL;
8524         rsurface.entityskeletaltransform3x4buffer = NULL;
8525         rsurface.entityskeletaltransform3x4offset = 0;
8526         rsurface.entityskeletaltransform3x4size = 0;;
8527         rsurface.entityskeletalnumtransforms = 0;
8528         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8529         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8531         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8532         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8534         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8535         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8536         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8537         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8538         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8539         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8540         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8541         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8542         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8543         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8544         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8545         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8546         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8547         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8548         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8549         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8550         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8551         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8552         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8553         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8554         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8555         rsurface.modelelement3i = model->surfmesh.data_element3i;
8556         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8557         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8558         rsurface.modelelement3s = model->surfmesh.data_element3s;
8559         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8560         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8561         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8562         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8563         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8564         rsurface.modelsurfaces = model->data_surfaces;
8565         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8566         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8567         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8568         rsurface.modelgeneratedvertex = false;
8569         rsurface.batchgeneratedvertex = false;
8570         rsurface.batchfirstvertex = 0;
8571         rsurface.batchnumvertices = 0;
8572         rsurface.batchfirsttriangle = 0;
8573         rsurface.batchnumtriangles = 0;
8574         rsurface.batchvertex3f  = NULL;
8575         rsurface.batchvertex3f_vertexbuffer = NULL;
8576         rsurface.batchvertex3f_bufferoffset = 0;
8577         rsurface.batchsvector3f = NULL;
8578         rsurface.batchsvector3f_vertexbuffer = NULL;
8579         rsurface.batchsvector3f_bufferoffset = 0;
8580         rsurface.batchtvector3f = NULL;
8581         rsurface.batchtvector3f_vertexbuffer = NULL;
8582         rsurface.batchtvector3f_bufferoffset = 0;
8583         rsurface.batchnormal3f  = NULL;
8584         rsurface.batchnormal3f_vertexbuffer = NULL;
8585         rsurface.batchnormal3f_bufferoffset = 0;
8586         rsurface.batchlightmapcolor4f = NULL;
8587         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8588         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8589         rsurface.batchtexcoordtexture2f = NULL;
8590         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8591         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8592         rsurface.batchtexcoordlightmap2f = NULL;
8593         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8594         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8595         rsurface.batchskeletalindex4ub = NULL;
8596         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8597         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8598         rsurface.batchskeletalweight4ub = NULL;
8599         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8600         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8601         rsurface.batchvertexmesh = NULL;
8602         rsurface.batchvertexmesh_vertexbuffer = NULL;
8603         rsurface.batchvertexmesh_bufferoffset = 0;
8604         rsurface.batchelement3i = NULL;
8605         rsurface.batchelement3i_indexbuffer = NULL;
8606         rsurface.batchelement3i_bufferoffset = 0;
8607         rsurface.batchelement3s = NULL;
8608         rsurface.batchelement3s_indexbuffer = NULL;
8609         rsurface.batchelement3s_bufferoffset = 0;
8610         rsurface.passcolor4f = NULL;
8611         rsurface.passcolor4f_vertexbuffer = NULL;
8612         rsurface.passcolor4f_bufferoffset = 0;
8613         rsurface.forcecurrenttextureupdate = false;
8614 }
8615
8616 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8617 {
8618         dp_model_t *model = ent->model;
8619         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8620         //      return;
8621         rsurface.entity = (entity_render_t *)ent;
8622         rsurface.skeleton = ent->skeleton;
8623         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8624         rsurface.ent_skinnum = ent->skinnum;
8625         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;
8626         rsurface.ent_flags = ent->flags;
8627         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8628         rsurface.matrix = ent->matrix;
8629         rsurface.inversematrix = ent->inversematrix;
8630         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8631         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8632         R_EntityMatrix(&rsurface.matrix);
8633         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8634         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8635         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8636         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8637         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8638         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8639         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8640         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8641         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8642         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8643         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8644         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8645         rsurface.colormod[3] = ent->alpha;
8646         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8647         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8648         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8649         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8650         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8651         if (ent->model->brush.submodel && !prepass)
8652         {
8653                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8654                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8655         }
8656         // if the animcache code decided it should use the shader path, skip the deform step
8657         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8658         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8659         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8660         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8661         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8662         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8663         {
8664                 if (ent->animcache_vertex3f)
8665                 {
8666                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8667                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8668                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8669                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8670                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8671                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8672                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8673                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8674                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8675                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8676                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8677                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8678                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8679                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8680                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8681                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8682                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8683                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8684                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8685                 }
8686                 else if (wanttangents)
8687                 {
8688                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8689                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8690                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8691                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8692                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8693                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8694                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8695                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8696                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8697                         rsurface.modelvertexmesh = NULL;
8698                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8699                         rsurface.modelvertexmesh_bufferoffset = 0;
8700                         rsurface.modelvertex3f_vertexbuffer = NULL;
8701                         rsurface.modelvertex3f_bufferoffset = 0;
8702                         rsurface.modelvertex3f_vertexbuffer = 0;
8703                         rsurface.modelvertex3f_bufferoffset = 0;
8704                         rsurface.modelsvector3f_vertexbuffer = 0;
8705                         rsurface.modelsvector3f_bufferoffset = 0;
8706                         rsurface.modeltvector3f_vertexbuffer = 0;
8707                         rsurface.modeltvector3f_bufferoffset = 0;
8708                         rsurface.modelnormal3f_vertexbuffer = 0;
8709                         rsurface.modelnormal3f_bufferoffset = 0;
8710                 }
8711                 else if (wantnormals)
8712                 {
8713                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8714                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8715                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8716                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8717                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8718                         rsurface.modelsvector3f = NULL;
8719                         rsurface.modeltvector3f = NULL;
8720                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8721                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8722                         rsurface.modelvertexmesh = NULL;
8723                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8724                         rsurface.modelvertexmesh_bufferoffset = 0;
8725                         rsurface.modelvertex3f_vertexbuffer = NULL;
8726                         rsurface.modelvertex3f_bufferoffset = 0;
8727                         rsurface.modelvertex3f_vertexbuffer = 0;
8728                         rsurface.modelvertex3f_bufferoffset = 0;
8729                         rsurface.modelsvector3f_vertexbuffer = 0;
8730                         rsurface.modelsvector3f_bufferoffset = 0;
8731                         rsurface.modeltvector3f_vertexbuffer = 0;
8732                         rsurface.modeltvector3f_bufferoffset = 0;
8733                         rsurface.modelnormal3f_vertexbuffer = 0;
8734                         rsurface.modelnormal3f_bufferoffset = 0;
8735                 }
8736                 else
8737                 {
8738                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8739                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8740                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8741                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8742                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8743                         rsurface.modelsvector3f = NULL;
8744                         rsurface.modeltvector3f = NULL;
8745                         rsurface.modelnormal3f = NULL;
8746                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8747                         rsurface.modelvertexmesh = NULL;
8748                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8749                         rsurface.modelvertexmesh_bufferoffset = 0;
8750                         rsurface.modelvertex3f_vertexbuffer = NULL;
8751                         rsurface.modelvertex3f_bufferoffset = 0;
8752                         rsurface.modelvertex3f_vertexbuffer = 0;
8753                         rsurface.modelvertex3f_bufferoffset = 0;
8754                         rsurface.modelsvector3f_vertexbuffer = 0;
8755                         rsurface.modelsvector3f_bufferoffset = 0;
8756                         rsurface.modeltvector3f_vertexbuffer = 0;
8757                         rsurface.modeltvector3f_bufferoffset = 0;
8758                         rsurface.modelnormal3f_vertexbuffer = 0;
8759                         rsurface.modelnormal3f_bufferoffset = 0;
8760                 }
8761                 rsurface.modelgeneratedvertex = true;
8762         }
8763         else
8764         {
8765                 if (rsurface.entityskeletaltransform3x4)
8766                 {
8767                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8768                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8769                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8770                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8771                 }
8772                 else
8773                 {
8774                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8775                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8776                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8777                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8778                 }
8779                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8780                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8781                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8782                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8783                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8784                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8785                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8786                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8787                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8788                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8789                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8790                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8791                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8792                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8793                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8794                 rsurface.modelgeneratedvertex = false;
8795         }
8796         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8797         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8798         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8799         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8800         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8801         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8802         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8803         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8804         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8805         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8806         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8807         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8808         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8809         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8810         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8811         rsurface.modelelement3i = model->surfmesh.data_element3i;
8812         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8813         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8814         rsurface.modelelement3s = model->surfmesh.data_element3s;
8815         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8816         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8817         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8818         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8819         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8820         rsurface.modelsurfaces = model->data_surfaces;
8821         rsurface.batchgeneratedvertex = false;
8822         rsurface.batchfirstvertex = 0;
8823         rsurface.batchnumvertices = 0;
8824         rsurface.batchfirsttriangle = 0;
8825         rsurface.batchnumtriangles = 0;
8826         rsurface.batchvertex3f  = NULL;
8827         rsurface.batchvertex3f_vertexbuffer = NULL;
8828         rsurface.batchvertex3f_bufferoffset = 0;
8829         rsurface.batchsvector3f = NULL;
8830         rsurface.batchsvector3f_vertexbuffer = NULL;
8831         rsurface.batchsvector3f_bufferoffset = 0;
8832         rsurface.batchtvector3f = NULL;
8833         rsurface.batchtvector3f_vertexbuffer = NULL;
8834         rsurface.batchtvector3f_bufferoffset = 0;
8835         rsurface.batchnormal3f  = NULL;
8836         rsurface.batchnormal3f_vertexbuffer = NULL;
8837         rsurface.batchnormal3f_bufferoffset = 0;
8838         rsurface.batchlightmapcolor4f = NULL;
8839         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8840         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8841         rsurface.batchtexcoordtexture2f = NULL;
8842         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8843         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8844         rsurface.batchtexcoordlightmap2f = NULL;
8845         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8846         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8847         rsurface.batchskeletalindex4ub = NULL;
8848         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8849         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8850         rsurface.batchskeletalweight4ub = NULL;
8851         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8852         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8853         rsurface.batchvertexmesh = NULL;
8854         rsurface.batchvertexmesh_vertexbuffer = NULL;
8855         rsurface.batchvertexmesh_bufferoffset = 0;
8856         rsurface.batchelement3i = NULL;
8857         rsurface.batchelement3i_indexbuffer = NULL;
8858         rsurface.batchelement3i_bufferoffset = 0;
8859         rsurface.batchelement3s = NULL;
8860         rsurface.batchelement3s_indexbuffer = NULL;
8861         rsurface.batchelement3s_bufferoffset = 0;
8862         rsurface.passcolor4f = NULL;
8863         rsurface.passcolor4f_vertexbuffer = NULL;
8864         rsurface.passcolor4f_bufferoffset = 0;
8865         rsurface.forcecurrenttextureupdate = false;
8866 }
8867
8868 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)
8869 {
8870         rsurface.entity = r_refdef.scene.worldentity;
8871         rsurface.skeleton = NULL;
8872         rsurface.ent_skinnum = 0;
8873         rsurface.ent_qwskin = -1;
8874         rsurface.ent_flags = entflags;
8875         rsurface.shadertime = r_refdef.scene.time - shadertime;
8876         rsurface.modelnumvertices = numvertices;
8877         rsurface.modelnumtriangles = numtriangles;
8878         rsurface.matrix = *matrix;
8879         rsurface.inversematrix = *inversematrix;
8880         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8881         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8882         R_EntityMatrix(&rsurface.matrix);
8883         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8884         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8885         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8886         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8887         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8888         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8889         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8890         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8891         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8892         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8893         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8894         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8895         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);
8896         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8897         rsurface.frameblend[0].lerp = 1;
8898         rsurface.ent_alttextures = false;
8899         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8900         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8901         rsurface.entityskeletaltransform3x4 = NULL;
8902         rsurface.entityskeletaltransform3x4buffer = NULL;
8903         rsurface.entityskeletaltransform3x4offset = 0;
8904         rsurface.entityskeletaltransform3x4size = 0;
8905         rsurface.entityskeletalnumtransforms = 0;
8906         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8907         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8908         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8909         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8910         if (wanttangents)
8911         {
8912                 rsurface.modelvertex3f = (float *)vertex3f;
8913                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8914                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8915                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8916         }
8917         else if (wantnormals)
8918         {
8919                 rsurface.modelvertex3f = (float *)vertex3f;
8920                 rsurface.modelsvector3f = NULL;
8921                 rsurface.modeltvector3f = NULL;
8922                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8923         }
8924         else
8925         {
8926                 rsurface.modelvertex3f = (float *)vertex3f;
8927                 rsurface.modelsvector3f = NULL;
8928                 rsurface.modeltvector3f = NULL;
8929                 rsurface.modelnormal3f = NULL;
8930         }
8931         rsurface.modelvertexmesh = NULL;
8932         rsurface.modelvertexmesh_vertexbuffer = NULL;
8933         rsurface.modelvertexmesh_bufferoffset = 0;
8934         rsurface.modelvertex3f_vertexbuffer = 0;
8935         rsurface.modelvertex3f_bufferoffset = 0;
8936         rsurface.modelsvector3f_vertexbuffer = 0;
8937         rsurface.modelsvector3f_bufferoffset = 0;
8938         rsurface.modeltvector3f_vertexbuffer = 0;
8939         rsurface.modeltvector3f_bufferoffset = 0;
8940         rsurface.modelnormal3f_vertexbuffer = 0;
8941         rsurface.modelnormal3f_bufferoffset = 0;
8942         rsurface.modelgeneratedvertex = true;
8943         rsurface.modellightmapcolor4f  = (float *)color4f;
8944         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8945         rsurface.modellightmapcolor4f_bufferoffset = 0;
8946         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8947         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8948         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8949         rsurface.modeltexcoordlightmap2f  = NULL;
8950         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8951         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8952         rsurface.modelskeletalindex4ub = NULL;
8953         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8954         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8955         rsurface.modelskeletalweight4ub = NULL;
8956         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8957         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8958         rsurface.modelelement3i = (int *)element3i;
8959         rsurface.modelelement3i_indexbuffer = NULL;
8960         rsurface.modelelement3i_bufferoffset = 0;
8961         rsurface.modelelement3s = (unsigned short *)element3s;
8962         rsurface.modelelement3s_indexbuffer = NULL;
8963         rsurface.modelelement3s_bufferoffset = 0;
8964         rsurface.modellightmapoffsets = NULL;
8965         rsurface.modelsurfaces = NULL;
8966         rsurface.batchgeneratedvertex = false;
8967         rsurface.batchfirstvertex = 0;
8968         rsurface.batchnumvertices = 0;
8969         rsurface.batchfirsttriangle = 0;
8970         rsurface.batchnumtriangles = 0;
8971         rsurface.batchvertex3f  = NULL;
8972         rsurface.batchvertex3f_vertexbuffer = NULL;
8973         rsurface.batchvertex3f_bufferoffset = 0;
8974         rsurface.batchsvector3f = NULL;
8975         rsurface.batchsvector3f_vertexbuffer = NULL;
8976         rsurface.batchsvector3f_bufferoffset = 0;
8977         rsurface.batchtvector3f = NULL;
8978         rsurface.batchtvector3f_vertexbuffer = NULL;
8979         rsurface.batchtvector3f_bufferoffset = 0;
8980         rsurface.batchnormal3f  = NULL;
8981         rsurface.batchnormal3f_vertexbuffer = NULL;
8982         rsurface.batchnormal3f_bufferoffset = 0;
8983         rsurface.batchlightmapcolor4f = NULL;
8984         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8985         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8986         rsurface.batchtexcoordtexture2f = NULL;
8987         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8988         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8989         rsurface.batchtexcoordlightmap2f = NULL;
8990         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8991         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8992         rsurface.batchskeletalindex4ub = NULL;
8993         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8994         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8995         rsurface.batchskeletalweight4ub = NULL;
8996         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8997         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8998         rsurface.batchvertexmesh = NULL;
8999         rsurface.batchvertexmesh_vertexbuffer = NULL;
9000         rsurface.batchvertexmesh_bufferoffset = 0;
9001         rsurface.batchelement3i = NULL;
9002         rsurface.batchelement3i_indexbuffer = NULL;
9003         rsurface.batchelement3i_bufferoffset = 0;
9004         rsurface.batchelement3s = NULL;
9005         rsurface.batchelement3s_indexbuffer = NULL;
9006         rsurface.batchelement3s_bufferoffset = 0;
9007         rsurface.passcolor4f = NULL;
9008         rsurface.passcolor4f_vertexbuffer = NULL;
9009         rsurface.passcolor4f_bufferoffset = 0;
9010         rsurface.forcecurrenttextureupdate = true;
9011
9012         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9013         {
9014                 if ((wantnormals || wanttangents) && !normal3f)
9015                 {
9016                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9017                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9018                 }
9019                 if (wanttangents && !svector3f)
9020                 {
9021                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9022                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9023                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9024                 }
9025         }
9026 }
9027
9028 float RSurf_FogPoint(const float *v)
9029 {
9030         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9031         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9032         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9033         float FogHeightFade = r_refdef.fogheightfade;
9034         float fogfrac;
9035         unsigned int fogmasktableindex;
9036         if (r_refdef.fogplaneviewabove)
9037                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9038         else
9039                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9040         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9041         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9042 }
9043
9044 float RSurf_FogVertex(const float *v)
9045 {
9046         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9047         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9048         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9049         float FogHeightFade = rsurface.fogheightfade;
9050         float fogfrac;
9051         unsigned int fogmasktableindex;
9052         if (r_refdef.fogplaneviewabove)
9053                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9054         else
9055                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9056         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9057         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9058 }
9059
9060 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9061 {
9062         int i;
9063         for (i = 0;i < numelements;i++)
9064                 outelement3i[i] = inelement3i[i] + adjust;
9065 }
9066
9067 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9068 extern cvar_t gl_vbo;
9069 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9070 {
9071         int deformindex;
9072         int firsttriangle;
9073         int numtriangles;
9074         int firstvertex;
9075         int endvertex;
9076         int numvertices;
9077         int surfacefirsttriangle;
9078         int surfacenumtriangles;
9079         int surfacefirstvertex;
9080         int surfaceendvertex;
9081         int surfacenumvertices;
9082         int batchnumsurfaces = texturenumsurfaces;
9083         int batchnumvertices;
9084         int batchnumtriangles;
9085         int needsupdate;
9086         int i, j;
9087         qboolean gaps;
9088         qboolean dynamicvertex;
9089         float amplitude;
9090         float animpos;
9091         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9092         float waveparms[4];
9093         unsigned char *ub;
9094         q3shaderinfo_deform_t *deform;
9095         const msurface_t *surface, *firstsurface;
9096         r_vertexmesh_t *vertexmesh;
9097         if (!texturenumsurfaces)
9098                 return;
9099         // find vertex range of this surface batch
9100         gaps = false;
9101         firstsurface = texturesurfacelist[0];
9102         firsttriangle = firstsurface->num_firsttriangle;
9103         batchnumvertices = 0;
9104         batchnumtriangles = 0;
9105         firstvertex = endvertex = firstsurface->num_firstvertex;
9106         for (i = 0;i < texturenumsurfaces;i++)
9107         {
9108                 surface = texturesurfacelist[i];
9109                 if (surface != firstsurface + i)
9110                         gaps = true;
9111                 surfacefirstvertex = surface->num_firstvertex;
9112                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9113                 surfacenumvertices = surface->num_vertices;
9114                 surfacenumtriangles = surface->num_triangles;
9115                 if (firstvertex > surfacefirstvertex)
9116                         firstvertex = surfacefirstvertex;
9117                 if (endvertex < surfaceendvertex)
9118                         endvertex = surfaceendvertex;
9119                 batchnumvertices += surfacenumvertices;
9120                 batchnumtriangles += surfacenumtriangles;
9121         }
9122
9123         r_refdef.stats[r_stat_batch_batches]++;
9124         if (gaps)
9125                 r_refdef.stats[r_stat_batch_withgaps]++;
9126         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9127         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9128         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9129
9130         // we now know the vertex range used, and if there are any gaps in it
9131         rsurface.batchfirstvertex = firstvertex;
9132         rsurface.batchnumvertices = endvertex - firstvertex;
9133         rsurface.batchfirsttriangle = firsttriangle;
9134         rsurface.batchnumtriangles = batchnumtriangles;
9135
9136         // this variable holds flags for which properties have been updated that
9137         // may require regenerating vertexmesh array...
9138         needsupdate = 0;
9139
9140         // check if any dynamic vertex processing must occur
9141         dynamicvertex = false;
9142
9143         // a cvar to force the dynamic vertex path to be taken, for debugging
9144         if (r_batch_debugdynamicvertexpath.integer)
9145         {
9146                 if (!dynamicvertex)
9147                 {
9148                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9149                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9150                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9151                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9152                 }
9153                 dynamicvertex = true;
9154         }
9155
9156         // if there is a chance of animated vertex colors, it's a dynamic batch
9157         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9158         {
9159                 if (!dynamicvertex)
9160                 {
9161                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9162                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9163                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9164                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9165                 }
9166                 dynamicvertex = true;
9167                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9168         }
9169
9170         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9171         {
9172                 switch (deform->deform)
9173                 {
9174                 default:
9175                 case Q3DEFORM_PROJECTIONSHADOW:
9176                 case Q3DEFORM_TEXT0:
9177                 case Q3DEFORM_TEXT1:
9178                 case Q3DEFORM_TEXT2:
9179                 case Q3DEFORM_TEXT3:
9180                 case Q3DEFORM_TEXT4:
9181                 case Q3DEFORM_TEXT5:
9182                 case Q3DEFORM_TEXT6:
9183                 case Q3DEFORM_TEXT7:
9184                 case Q3DEFORM_NONE:
9185                         break;
9186                 case Q3DEFORM_AUTOSPRITE:
9187                         if (!dynamicvertex)
9188                         {
9189                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9190                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9191                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9192                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9193                         }
9194                         dynamicvertex = true;
9195                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9196                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9197                         break;
9198                 case Q3DEFORM_AUTOSPRITE2:
9199                         if (!dynamicvertex)
9200                         {
9201                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9202                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9203                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9204                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9205                         }
9206                         dynamicvertex = true;
9207                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9208                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9209                         break;
9210                 case Q3DEFORM_NORMAL:
9211                         if (!dynamicvertex)
9212                         {
9213                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9214                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9215                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9216                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9217                         }
9218                         dynamicvertex = true;
9219                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9220                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9221                         break;
9222                 case Q3DEFORM_WAVE:
9223                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9224                                 break; // if wavefunc is a nop, ignore this transform
9225                         if (!dynamicvertex)
9226                         {
9227                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9228                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9229                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9230                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9231                         }
9232                         dynamicvertex = true;
9233                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9234                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9235                         break;
9236                 case Q3DEFORM_BULGE:
9237                         if (!dynamicvertex)
9238                         {
9239                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9240                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9241                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9242                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9243                         }
9244                         dynamicvertex = true;
9245                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9246                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9247                         break;
9248                 case Q3DEFORM_MOVE:
9249                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9250                                 break; // if wavefunc is a nop, ignore this transform
9251                         if (!dynamicvertex)
9252                         {
9253                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9254                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9255                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9256                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9257                         }
9258                         dynamicvertex = true;
9259                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9260                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9261                         break;
9262                 }
9263         }
9264         switch(rsurface.texture->tcgen.tcgen)
9265         {
9266         default:
9267         case Q3TCGEN_TEXTURE:
9268                 break;
9269         case Q3TCGEN_LIGHTMAP:
9270                 if (!dynamicvertex)
9271                 {
9272                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9273                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9274                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9275                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9276                 }
9277                 dynamicvertex = true;
9278                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9279                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9280                 break;
9281         case Q3TCGEN_VECTOR:
9282                 if (!dynamicvertex)
9283                 {
9284                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9285                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9286                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9287                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9288                 }
9289                 dynamicvertex = true;
9290                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9291                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9292                 break;
9293         case Q3TCGEN_ENVIRONMENT:
9294                 if (!dynamicvertex)
9295                 {
9296                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9297                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9298                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9299                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9300                 }
9301                 dynamicvertex = true;
9302                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9303                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9304                 break;
9305         }
9306         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9307         {
9308                 if (!dynamicvertex)
9309                 {
9310                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9311                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9312                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9313                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9314                 }
9315                 dynamicvertex = true;
9316                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9317                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9318         }
9319
9320         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9321         {
9322                 if (!dynamicvertex)
9323                 {
9324                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9325                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9326                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9327                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9328                 }
9329                 dynamicvertex = true;
9330                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9331         }
9332
9333         // when the model data has no vertex buffer (dynamic mesh), we need to
9334         // eliminate gaps
9335         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9336                 batchneed |= BATCHNEED_NOGAPS;
9337
9338         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9339         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9340         // we ensure this by treating the vertex batch as dynamic...
9341         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9342         {
9343                 if (!dynamicvertex)
9344                 {
9345                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9346                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9347                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9348                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9349                 }
9350                 dynamicvertex = true;
9351         }
9352
9353         if (dynamicvertex)
9354         {
9355                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9356                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9357                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9358                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9359                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9360                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9361                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9362                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9363         }
9364
9365         // if needsupdate, we have to do a dynamic vertex batch for sure
9366         if (needsupdate & batchneed)
9367         {
9368                 if (!dynamicvertex)
9369                 {
9370                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9371                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9372                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9373                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9374                 }
9375                 dynamicvertex = true;
9376         }
9377
9378         // see if we need to build vertexmesh from arrays
9379         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9380         {
9381                 if (!dynamicvertex)
9382                 {
9383                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9384                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9385                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9386                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9387                 }
9388                 dynamicvertex = true;
9389         }
9390
9391         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9392         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9393                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9394
9395         rsurface.batchvertex3f = rsurface.modelvertex3f;
9396         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9397         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9398         rsurface.batchsvector3f = rsurface.modelsvector3f;
9399         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9400         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9401         rsurface.batchtvector3f = rsurface.modeltvector3f;
9402         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9403         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9404         rsurface.batchnormal3f = rsurface.modelnormal3f;
9405         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9406         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9407         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9408         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9409         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9410         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9411         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9412         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9413         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9414         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9415         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9416         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9417         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9418         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9419         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9420         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9421         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9422         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9423         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9424         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9425         rsurface.batchelement3i = rsurface.modelelement3i;
9426         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9427         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9428         rsurface.batchelement3s = rsurface.modelelement3s;
9429         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9430         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9431         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9432         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9433         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9434         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9435         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9436
9437         // if any dynamic vertex processing has to occur in software, we copy the
9438         // entire surface list together before processing to rebase the vertices
9439         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9440         //
9441         // if any gaps exist and we do not have a static vertex buffer, we have to
9442         // copy the surface list together to avoid wasting upload bandwidth on the
9443         // vertices in the gaps.
9444         //
9445         // if gaps exist and we have a static vertex buffer, we can choose whether
9446         // to combine the index buffer ranges into one dynamic index buffer or
9447         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9448         //
9449         // in many cases the batch is reduced to one draw call.
9450
9451         rsurface.batchmultidraw = false;
9452         rsurface.batchmultidrawnumsurfaces = 0;
9453         rsurface.batchmultidrawsurfacelist = NULL;
9454
9455         if (!dynamicvertex)
9456         {
9457                 // static vertex data, just set pointers...
9458                 rsurface.batchgeneratedvertex = false;
9459                 // if there are gaps, we want to build a combined index buffer,
9460                 // otherwise use the original static buffer with an appropriate offset
9461                 if (gaps)
9462                 {
9463                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9464                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9465                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9466                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9467                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9468                         {
9469                                 rsurface.batchmultidraw = true;
9470                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9471                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9472                                 return;
9473                         }
9474                         // build a new triangle elements array for this batch
9475                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9476                         rsurface.batchfirsttriangle = 0;
9477                         numtriangles = 0;
9478                         for (i = 0;i < texturenumsurfaces;i++)
9479                         {
9480                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9481                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9482                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9483                                 numtriangles += surfacenumtriangles;
9484                         }
9485                         rsurface.batchelement3i_indexbuffer = NULL;
9486                         rsurface.batchelement3i_bufferoffset = 0;
9487                         rsurface.batchelement3s = NULL;
9488                         rsurface.batchelement3s_indexbuffer = NULL;
9489                         rsurface.batchelement3s_bufferoffset = 0;
9490                         if (endvertex <= 65536)
9491                         {
9492                                 // make a 16bit (unsigned short) index array if possible
9493                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9494                                 for (i = 0;i < numtriangles*3;i++)
9495                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9496                         }
9497                         // upload buffer data for the copytriangles batch
9498                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9499                         {
9500                                 if (rsurface.batchelement3s)
9501                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9502                                 else if (rsurface.batchelement3i)
9503                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9504                         }
9505                 }
9506                 else
9507                 {
9508                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9509                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9510                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9511                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9512                 }
9513                 return;
9514         }
9515
9516         // something needs software processing, do it for real...
9517         // we only directly handle separate array data in this case and then
9518         // generate interleaved data if needed...
9519         rsurface.batchgeneratedvertex = true;
9520         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9521         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9522         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9523         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9524
9525         // now copy the vertex data into a combined array and make an index array
9526         // (this is what Quake3 does all the time)
9527         // we also apply any skeletal animation here that would have been done in
9528         // the vertex shader, because most of the dynamic vertex animation cases
9529         // need actual vertex positions and normals
9530         //if (dynamicvertex)
9531         {
9532                 rsurface.batchvertexmesh = NULL;
9533                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9534                 rsurface.batchvertexmesh_bufferoffset = 0;
9535                 rsurface.batchvertex3f = NULL;
9536                 rsurface.batchvertex3f_vertexbuffer = NULL;
9537                 rsurface.batchvertex3f_bufferoffset = 0;
9538                 rsurface.batchsvector3f = NULL;
9539                 rsurface.batchsvector3f_vertexbuffer = NULL;
9540                 rsurface.batchsvector3f_bufferoffset = 0;
9541                 rsurface.batchtvector3f = NULL;
9542                 rsurface.batchtvector3f_vertexbuffer = NULL;
9543                 rsurface.batchtvector3f_bufferoffset = 0;
9544                 rsurface.batchnormal3f = NULL;
9545                 rsurface.batchnormal3f_vertexbuffer = NULL;
9546                 rsurface.batchnormal3f_bufferoffset = 0;
9547                 rsurface.batchlightmapcolor4f = NULL;
9548                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9549                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9550                 rsurface.batchtexcoordtexture2f = NULL;
9551                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9552                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9553                 rsurface.batchtexcoordlightmap2f = NULL;
9554                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9555                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9556                 rsurface.batchskeletalindex4ub = NULL;
9557                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9558                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9559                 rsurface.batchskeletalweight4ub = NULL;
9560                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9561                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9562                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9563                 rsurface.batchelement3i_indexbuffer = NULL;
9564                 rsurface.batchelement3i_bufferoffset = 0;
9565                 rsurface.batchelement3s = NULL;
9566                 rsurface.batchelement3s_indexbuffer = NULL;
9567                 rsurface.batchelement3s_bufferoffset = 0;
9568                 rsurface.batchskeletaltransform3x4buffer = NULL;
9569                 rsurface.batchskeletaltransform3x4offset = 0;
9570                 rsurface.batchskeletaltransform3x4size = 0;
9571                 // we'll only be setting up certain arrays as needed
9572                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9573                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9574                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9575                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9576                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9577                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9578                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9579                 {
9580                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9581                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9582                 }
9583                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9584                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9585                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9586                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9587                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9588                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9589                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9590                 {
9591                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9592                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9593                 }
9594                 numvertices = 0;
9595                 numtriangles = 0;
9596                 for (i = 0;i < texturenumsurfaces;i++)
9597                 {
9598                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9599                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9600                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9601                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9602                         // copy only the data requested
9603                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9604                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9605                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9606                         {
9607                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9608                                 {
9609                                         if (rsurface.batchvertex3f)
9610                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9611                                         else
9612                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9613                                 }
9614                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9615                                 {
9616                                         if (rsurface.modelnormal3f)
9617                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9618                                         else
9619                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9620                                 }
9621                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9622                                 {
9623                                         if (rsurface.modelsvector3f)
9624                                         {
9625                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9626                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9627                                         }
9628                                         else
9629                                         {
9630                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9631                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9632                                         }
9633                                 }
9634                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9635                                 {
9636                                         if (rsurface.modellightmapcolor4f)
9637                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9638                                         else
9639                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9640                                 }
9641                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9642                                 {
9643                                         if (rsurface.modeltexcoordtexture2f)
9644                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9645                                         else
9646                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9647                                 }
9648                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9649                                 {
9650                                         if (rsurface.modeltexcoordlightmap2f)
9651                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9652                                         else
9653                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9654                                 }
9655                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9656                                 {
9657                                         if (rsurface.modelskeletalindex4ub)
9658                                         {
9659                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9660                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9661                                         }
9662                                         else
9663                                         {
9664                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9665                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9666                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9667                                                 for (j = 0;j < surfacenumvertices;j++)
9668                                                         ub[j*4] = 255;
9669                                         }
9670                                 }
9671                         }
9672                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9673                         numvertices += surfacenumvertices;
9674                         numtriangles += surfacenumtriangles;
9675                 }
9676
9677                 // generate a 16bit index array as well if possible
9678                 // (in general, dynamic batches fit)
9679                 if (numvertices <= 65536)
9680                 {
9681                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9682                         for (i = 0;i < numtriangles*3;i++)
9683                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9684                 }
9685
9686                 // since we've copied everything, the batch now starts at 0
9687                 rsurface.batchfirstvertex = 0;
9688                 rsurface.batchnumvertices = batchnumvertices;
9689                 rsurface.batchfirsttriangle = 0;
9690                 rsurface.batchnumtriangles = batchnumtriangles;
9691         }
9692
9693         // apply skeletal animation that would have been done in the vertex shader
9694         if (rsurface.batchskeletaltransform3x4)
9695         {
9696                 const unsigned char *si;
9697                 const unsigned char *sw;
9698                 const float *t[4];
9699                 const float *b = rsurface.batchskeletaltransform3x4;
9700                 float *vp, *vs, *vt, *vn;
9701                 float w[4];
9702                 float m[3][4], n[3][4];
9703                 float tp[3], ts[3], tt[3], tn[3];
9704                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9705                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9706                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9707                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9708                 si = rsurface.batchskeletalindex4ub;
9709                 sw = rsurface.batchskeletalweight4ub;
9710                 vp = rsurface.batchvertex3f;
9711                 vs = rsurface.batchsvector3f;
9712                 vt = rsurface.batchtvector3f;
9713                 vn = rsurface.batchnormal3f;
9714                 memset(m[0], 0, sizeof(m));
9715                 memset(n[0], 0, sizeof(n));
9716                 for (i = 0;i < batchnumvertices;i++)
9717                 {
9718                         t[0] = b + si[0]*12;
9719                         if (sw[0] == 255)
9720                         {
9721                                 // common case - only one matrix
9722                                 m[0][0] = t[0][ 0];
9723                                 m[0][1] = t[0][ 1];
9724                                 m[0][2] = t[0][ 2];
9725                                 m[0][3] = t[0][ 3];
9726                                 m[1][0] = t[0][ 4];
9727                                 m[1][1] = t[0][ 5];
9728                                 m[1][2] = t[0][ 6];
9729                                 m[1][3] = t[0][ 7];
9730                                 m[2][0] = t[0][ 8];
9731                                 m[2][1] = t[0][ 9];
9732                                 m[2][2] = t[0][10];
9733                                 m[2][3] = t[0][11];
9734                         }
9735                         else if (sw[2] + sw[3])
9736                         {
9737                                 // blend 4 matrices
9738                                 t[1] = b + si[1]*12;
9739                                 t[2] = b + si[2]*12;
9740                                 t[3] = b + si[3]*12;
9741                                 w[0] = sw[0] * (1.0f / 255.0f);
9742                                 w[1] = sw[1] * (1.0f / 255.0f);
9743                                 w[2] = sw[2] * (1.0f / 255.0f);
9744                                 w[3] = sw[3] * (1.0f / 255.0f);
9745                                 // blend the matrices
9746                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9747                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9748                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9749                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9750                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9751                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9752                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9753                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9754                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9755                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9756                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9757                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9758                         }
9759                         else
9760                         {
9761                                 // blend 2 matrices
9762                                 t[1] = b + si[1]*12;
9763                                 w[0] = sw[0] * (1.0f / 255.0f);
9764                                 w[1] = sw[1] * (1.0f / 255.0f);
9765                                 // blend the matrices
9766                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9767                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9768                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9769                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9770                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9771                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9772                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9773                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9774                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9775                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9776                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9777                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9778                         }
9779                         si += 4;
9780                         sw += 4;
9781                         // modify the vertex
9782                         VectorCopy(vp, tp);
9783                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9784                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9785                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9786                         vp += 3;
9787                         if (vn)
9788                         {
9789                                 // the normal transformation matrix is a set of cross products...
9790                                 CrossProduct(m[1], m[2], n[0]);
9791                                 CrossProduct(m[2], m[0], n[1]);
9792                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9793                                 VectorCopy(vn, tn);
9794                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9795                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9796                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9797                                 VectorNormalize(vn);
9798                                 vn += 3;
9799                                 if (vs)
9800                                 {
9801                                         VectorCopy(vs, ts);
9802                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9803                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9804                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9805                                         VectorNormalize(vs);
9806                                         vs += 3;
9807                                         VectorCopy(vt, tt);
9808                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9809                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9810                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9811                                         VectorNormalize(vt);
9812                                         vt += 3;
9813                                 }
9814                         }
9815                 }
9816                 rsurface.batchskeletaltransform3x4 = NULL;
9817                 rsurface.batchskeletalnumtransforms = 0;
9818         }
9819
9820         // q1bsp surfaces rendered in vertex color mode have to have colors
9821         // calculated based on lightstyles
9822         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9823         {
9824                 // generate color arrays for the surfaces in this list
9825                 int c[4];
9826                 int scale;
9827                 int size3;
9828                 const int *offsets;
9829                 const unsigned char *lm;
9830                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9831                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9832                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9833                 numvertices = 0;
9834                 for (i = 0;i < texturenumsurfaces;i++)
9835                 {
9836                         surface = texturesurfacelist[i];
9837                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9838                         surfacenumvertices = surface->num_vertices;
9839                         if (surface->lightmapinfo->samples)
9840                         {
9841                                 for (j = 0;j < surfacenumvertices;j++)
9842                                 {
9843                                         lm = surface->lightmapinfo->samples + offsets[j];
9844                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9845                                         VectorScale(lm, scale, c);
9846                                         if (surface->lightmapinfo->styles[1] != 255)
9847                                         {
9848                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9849                                                 lm += size3;
9850                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9851                                                 VectorMA(c, scale, lm, c);
9852                                                 if (surface->lightmapinfo->styles[2] != 255)
9853                                                 {
9854                                                         lm += size3;
9855                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9856                                                         VectorMA(c, scale, lm, c);
9857                                                         if (surface->lightmapinfo->styles[3] != 255)
9858                                                         {
9859                                                                 lm += size3;
9860                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9861                                                                 VectorMA(c, scale, lm, c);
9862                                                         }
9863                                                 }
9864                                         }
9865                                         c[0] >>= 7;
9866                                         c[1] >>= 7;
9867                                         c[2] >>= 7;
9868                                         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);
9869                                         numvertices++;
9870                                 }
9871                         }
9872                         else
9873                         {
9874                                 for (j = 0;j < surfacenumvertices;j++)
9875                                 {
9876                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9877                                         numvertices++;
9878                                 }
9879                         }
9880                 }
9881         }
9882
9883         // if vertices are deformed (sprite flares and things in maps, possibly
9884         // water waves, bulges and other deformations), modify the copied vertices
9885         // in place
9886         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9887         {
9888                 float scale;
9889                 switch (deform->deform)
9890                 {
9891                 default:
9892                 case Q3DEFORM_PROJECTIONSHADOW:
9893                 case Q3DEFORM_TEXT0:
9894                 case Q3DEFORM_TEXT1:
9895                 case Q3DEFORM_TEXT2:
9896                 case Q3DEFORM_TEXT3:
9897                 case Q3DEFORM_TEXT4:
9898                 case Q3DEFORM_TEXT5:
9899                 case Q3DEFORM_TEXT6:
9900                 case Q3DEFORM_TEXT7:
9901                 case Q3DEFORM_NONE:
9902                         break;
9903                 case Q3DEFORM_AUTOSPRITE:
9904                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9905                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9906                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9907                         VectorNormalize(newforward);
9908                         VectorNormalize(newright);
9909                         VectorNormalize(newup);
9910 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9911 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9912 //                      rsurface.batchvertex3f_bufferoffset = 0;
9913 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9914 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9915 //                      rsurface.batchsvector3f_bufferoffset = 0;
9916 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9917 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9918 //                      rsurface.batchtvector3f_bufferoffset = 0;
9919 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9920 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9921 //                      rsurface.batchnormal3f_bufferoffset = 0;
9922                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9923                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9924                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9925                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9926                                 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);
9927                         // a single autosprite surface can contain multiple sprites...
9928                         for (j = 0;j < batchnumvertices - 3;j += 4)
9929                         {
9930                                 VectorClear(center);
9931                                 for (i = 0;i < 4;i++)
9932                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9933                                 VectorScale(center, 0.25f, center);
9934                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9935                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9936                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9937                                 for (i = 0;i < 4;i++)
9938                                 {
9939                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9940                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9941                                 }
9942                         }
9943                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9944                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9945                         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);
9946                         break;
9947                 case Q3DEFORM_AUTOSPRITE2:
9948                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9949                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9950                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9951                         VectorNormalize(newforward);
9952                         VectorNormalize(newright);
9953                         VectorNormalize(newup);
9954 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9955 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9956 //                      rsurface.batchvertex3f_bufferoffset = 0;
9957                         {
9958                                 const float *v1, *v2;
9959                                 vec3_t start, end;
9960                                 float f, l;
9961                                 struct
9962                                 {
9963                                         float length2;
9964                                         const float *v1;
9965                                         const float *v2;
9966                                 }
9967                                 shortest[2];
9968                                 memset(shortest, 0, sizeof(shortest));
9969                                 // a single autosprite surface can contain multiple sprites...
9970                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9971                                 {
9972                                         VectorClear(center);
9973                                         for (i = 0;i < 4;i++)
9974                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9975                                         VectorScale(center, 0.25f, center);
9976                                         // find the two shortest edges, then use them to define the
9977                                         // axis vectors for rotating around the central axis
9978                                         for (i = 0;i < 6;i++)
9979                                         {
9980                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9981                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9982                                                 l = VectorDistance2(v1, v2);
9983                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9984                                                 if (v1[2] != v2[2])
9985                                                         l += (1.0f / 1024.0f);
9986                                                 if (shortest[0].length2 > l || i == 0)
9987                                                 {
9988                                                         shortest[1] = shortest[0];
9989                                                         shortest[0].length2 = l;
9990                                                         shortest[0].v1 = v1;
9991                                                         shortest[0].v2 = v2;
9992                                                 }
9993                                                 else if (shortest[1].length2 > l || i == 1)
9994                                                 {
9995                                                         shortest[1].length2 = l;
9996                                                         shortest[1].v1 = v1;
9997                                                         shortest[1].v2 = v2;
9998                                                 }
9999                                         }
10000                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10001                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10002                                         // this calculates the right vector from the shortest edge
10003                                         // and the up vector from the edge midpoints
10004                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10005                                         VectorNormalize(right);
10006                                         VectorSubtract(end, start, up);
10007                                         VectorNormalize(up);
10008                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10009                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10010                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10011                                         VectorNegate(forward, forward);
10012                                         VectorReflect(forward, 0, up, forward);
10013                                         VectorNormalize(forward);
10014                                         CrossProduct(up, forward, newright);
10015                                         VectorNormalize(newright);
10016                                         // rotate the quad around the up axis vector, this is made
10017                                         // especially easy by the fact we know the quad is flat,
10018                                         // so we only have to subtract the center position and
10019                                         // measure distance along the right vector, and then
10020                                         // multiply that by the newright vector and add back the
10021                                         // center position
10022                                         // we also need to subtract the old position to undo the
10023                                         // displacement from the center, which we do with a
10024                                         // DotProduct, the subtraction/addition of center is also
10025                                         // optimized into DotProducts here
10026                                         l = DotProduct(right, center);
10027                                         for (i = 0;i < 4;i++)
10028                                         {
10029                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10030                                                 f = DotProduct(right, v1) - l;
10031                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10032                                         }
10033                                 }
10034                         }
10035                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10036                         {
10037 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10038 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10039 //                              rsurface.batchnormal3f_bufferoffset = 0;
10040                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10041                         }
10042                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10043                         {
10044 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10045 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10046 //                              rsurface.batchsvector3f_bufferoffset = 0;
10047 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10048 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10049 //                              rsurface.batchtvector3f_bufferoffset = 0;
10050                                 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);
10051                         }
10052                         break;
10053                 case Q3DEFORM_NORMAL:
10054                         // deform the normals to make reflections wavey
10055                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10056                         rsurface.batchnormal3f_vertexbuffer = NULL;
10057                         rsurface.batchnormal3f_bufferoffset = 0;
10058                         for (j = 0;j < batchnumvertices;j++)
10059                         {
10060                                 float vertex[3];
10061                                 float *normal = rsurface.batchnormal3f + 3*j;
10062                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10063                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10064                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10065                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10066                                 VectorNormalize(normal);
10067                         }
10068                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10069                         {
10070 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10071 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10072 //                              rsurface.batchsvector3f_bufferoffset = 0;
10073 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10074 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10075 //                              rsurface.batchtvector3f_bufferoffset = 0;
10076                                 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);
10077                         }
10078                         break;
10079                 case Q3DEFORM_WAVE:
10080                         // deform vertex array to make wavey water and flags and such
10081                         waveparms[0] = deform->waveparms[0];
10082                         waveparms[1] = deform->waveparms[1];
10083                         waveparms[2] = deform->waveparms[2];
10084                         waveparms[3] = deform->waveparms[3];
10085                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10086                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10087                         // this is how a divisor of vertex influence on deformation
10088                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10089                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10090 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10091 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10092 //                      rsurface.batchvertex3f_bufferoffset = 0;
10093 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10094 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10095 //                      rsurface.batchnormal3f_bufferoffset = 0;
10096                         for (j = 0;j < batchnumvertices;j++)
10097                         {
10098                                 // if the wavefunc depends on time, evaluate it per-vertex
10099                                 if (waveparms[3])
10100                                 {
10101                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10102                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10103                                 }
10104                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10105                         }
10106                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10107                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10108                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10109                         {
10110 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10111 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10112 //                              rsurface.batchsvector3f_bufferoffset = 0;
10113 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10114 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10115 //                              rsurface.batchtvector3f_bufferoffset = 0;
10116                                 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);
10117                         }
10118                         break;
10119                 case Q3DEFORM_BULGE:
10120                         // deform vertex array to make the surface have moving bulges
10121 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10122 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10123 //                      rsurface.batchvertex3f_bufferoffset = 0;
10124 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10125 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10126 //                      rsurface.batchnormal3f_bufferoffset = 0;
10127                         for (j = 0;j < batchnumvertices;j++)
10128                         {
10129                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10130                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10131                         }
10132                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10133                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10134                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10135                         {
10136 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10137 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10138 //                              rsurface.batchsvector3f_bufferoffset = 0;
10139 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10140 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10141 //                              rsurface.batchtvector3f_bufferoffset = 0;
10142                                 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);
10143                         }
10144                         break;
10145                 case Q3DEFORM_MOVE:
10146                         // deform vertex array
10147                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10148                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10149                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10150                         VectorScale(deform->parms, scale, waveparms);
10151 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10152 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10153 //                      rsurface.batchvertex3f_bufferoffset = 0;
10154                         for (j = 0;j < batchnumvertices;j++)
10155                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10156                         break;
10157                 }
10158         }
10159
10160         if (rsurface.batchtexcoordtexture2f)
10161         {
10162         // generate texcoords based on the chosen texcoord source
10163                 switch(rsurface.texture->tcgen.tcgen)
10164                 {
10165                 default:
10166                 case Q3TCGEN_TEXTURE:
10167                         break;
10168                 case Q3TCGEN_LIGHTMAP:
10169         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10170         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10171         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10172                         if (rsurface.batchtexcoordlightmap2f)
10173                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10174                         break;
10175                 case Q3TCGEN_VECTOR:
10176         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10177         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10178         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10179                         for (j = 0;j < batchnumvertices;j++)
10180                         {
10181                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10182                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10183                         }
10184                         break;
10185                 case Q3TCGEN_ENVIRONMENT:
10186                         // make environment reflections using a spheremap
10187                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10188                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10189                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10190                         for (j = 0;j < batchnumvertices;j++)
10191                         {
10192                                 // identical to Q3A's method, but executed in worldspace so
10193                                 // carried models can be shiny too
10194
10195                                 float viewer[3], d, reflected[3], worldreflected[3];
10196
10197                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10198                                 // VectorNormalize(viewer);
10199
10200                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10201
10202                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10203                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10204                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10205                                 // note: this is proportinal to viewer, so we can normalize later
10206
10207                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10208                                 VectorNormalize(worldreflected);
10209
10210                                 // note: this sphere map only uses world x and z!
10211                                 // so positive and negative y will LOOK THE SAME.
10212                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10213                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10214                         }
10215                         break;
10216                 }
10217                 // the only tcmod that needs software vertex processing is turbulent, so
10218                 // check for it here and apply the changes if needed
10219                 // and we only support that as the first one
10220                 // (handling a mixture of turbulent and other tcmods would be problematic
10221                 //  without punting it entirely to a software path)
10222                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10223                 {
10224                         amplitude = rsurface.texture->tcmods[0].parms[1];
10225                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10226         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10227         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10228         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10229                         for (j = 0;j < batchnumvertices;j++)
10230                         {
10231                                 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);
10232                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10233                         }
10234                 }
10235         }
10236
10237         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10238         {
10239                 // convert the modified arrays to vertex structs
10240 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10241 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10242 //              rsurface.batchvertexmesh_bufferoffset = 0;
10243                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10244                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10245                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10246                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10247                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10248                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10249                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10250                 {
10251                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10252                         {
10253                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10254                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10255                         }
10256                 }
10257                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10258                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10259                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10260                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10261                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10262                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10263                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10264                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10265                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10266                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10267                 {
10268                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10269                         {
10270                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10271                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10272                         }
10273                 }
10274         }
10275
10276         // upload buffer data for the dynamic batch
10277         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10278         {
10279                 if (rsurface.batchvertexmesh)
10280                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10281                 else
10282                 {
10283                         if (rsurface.batchvertex3f)
10284                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10285                         if (rsurface.batchsvector3f)
10286                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10287                         if (rsurface.batchtvector3f)
10288                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10289                         if (rsurface.batchnormal3f)
10290                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10291                         if (rsurface.batchlightmapcolor4f)
10292                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10293                         if (rsurface.batchtexcoordtexture2f)
10294                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10295                         if (rsurface.batchtexcoordlightmap2f)
10296                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10297                         if (rsurface.batchskeletalindex4ub)
10298                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10299                         if (rsurface.batchskeletalweight4ub)
10300                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10301                 }
10302                 if (rsurface.batchelement3s)
10303                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10304                 else if (rsurface.batchelement3i)
10305                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10306         }
10307 }
10308
10309 void RSurf_DrawBatch(void)
10310 {
10311         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10312         // through the pipeline, killing it earlier in the pipeline would have
10313         // per-surface overhead rather than per-batch overhead, so it's best to
10314         // reject it here, before it hits glDraw.
10315         if (rsurface.batchnumtriangles == 0)
10316                 return;
10317 #if 0
10318         // batch debugging code
10319         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10320         {
10321                 int i;
10322                 int j;
10323                 int c;
10324                 const int *e;
10325                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10326                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10327                 {
10328                         c = e[i];
10329                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10330                         {
10331                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10332                                 {
10333                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10334                                                 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);
10335                                         break;
10336                                 }
10337                         }
10338                 }
10339         }
10340 #endif
10341         if (rsurface.batchmultidraw)
10342         {
10343                 // issue multiple draws rather than copying index data
10344                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10345                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10346                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10347                 for (i = 0;i < numsurfaces;)
10348                 {
10349                         // combine consecutive surfaces as one draw
10350                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10351                                 if (surfacelist[j] != surfacelist[k] + 1)
10352                                         break;
10353                         firstvertex = surfacelist[i]->num_firstvertex;
10354                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10355                         firsttriangle = surfacelist[i]->num_firsttriangle;
10356                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10357                         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);
10358                         i = j;
10359                 }
10360         }
10361         else
10362         {
10363                 // there is only one consecutive run of index data (may have been combined)
10364                 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);
10365         }
10366 }
10367
10368 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10369 {
10370         // pick the closest matching water plane
10371         int planeindex, vertexindex, bestplaneindex = -1;
10372         float d, bestd;
10373         vec3_t vert;
10374         const float *v;
10375         r_waterstate_waterplane_t *p;
10376         qboolean prepared = false;
10377         bestd = 0;
10378         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10379         {
10380                 if(p->camera_entity != rsurface.texture->camera_entity)
10381                         continue;
10382                 d = 0;
10383                 if(!prepared)
10384                 {
10385                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10386                         prepared = true;
10387                         if(rsurface.batchnumvertices == 0)
10388                                 break;
10389                 }
10390                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10391                 {
10392                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10393                         d += fabs(PlaneDiff(vert, &p->plane));
10394                 }
10395                 if (bestd > d || bestplaneindex < 0)
10396                 {
10397                         bestd = d;
10398                         bestplaneindex = planeindex;
10399                 }
10400         }
10401         return bestplaneindex;
10402         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10403         // this situation though, as it might be better to render single larger
10404         // batches with useless stuff (backface culled for example) than to
10405         // render multiple smaller batches
10406 }
10407
10408 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10409 {
10410         int i;
10411         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10412         rsurface.passcolor4f_vertexbuffer = 0;
10413         rsurface.passcolor4f_bufferoffset = 0;
10414         for (i = 0;i < rsurface.batchnumvertices;i++)
10415                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10416 }
10417
10418 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10419 {
10420         int i;
10421         float f;
10422         const float *v;
10423         const float *c;
10424         float *c2;
10425         if (rsurface.passcolor4f)
10426         {
10427                 // generate color arrays
10428                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10429                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10430                 rsurface.passcolor4f_vertexbuffer = 0;
10431                 rsurface.passcolor4f_bufferoffset = 0;
10432                 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)
10433                 {
10434                         f = RSurf_FogVertex(v);
10435                         c2[0] = c[0] * f;
10436                         c2[1] = c[1] * f;
10437                         c2[2] = c[2] * f;
10438                         c2[3] = c[3];
10439                 }
10440         }
10441         else
10442         {
10443                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10444                 rsurface.passcolor4f_vertexbuffer = 0;
10445                 rsurface.passcolor4f_bufferoffset = 0;
10446                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10447                 {
10448                         f = RSurf_FogVertex(v);
10449                         c2[0] = f;
10450                         c2[1] = f;
10451                         c2[2] = f;
10452                         c2[3] = 1;
10453                 }
10454         }
10455 }
10456
10457 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10458 {
10459         int i;
10460         float f;
10461         const float *v;
10462         const float *c;
10463         float *c2;
10464         if (!rsurface.passcolor4f)
10465                 return;
10466         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10467         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10468         rsurface.passcolor4f_vertexbuffer = 0;
10469         rsurface.passcolor4f_bufferoffset = 0;
10470         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)
10471         {
10472                 f = RSurf_FogVertex(v);
10473                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10474                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10475                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10476                 c2[3] = c[3];
10477         }
10478 }
10479
10480 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10481 {
10482         int i;
10483         const float *c;
10484         float *c2;
10485         if (!rsurface.passcolor4f)
10486                 return;
10487         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10488         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10489         rsurface.passcolor4f_vertexbuffer = 0;
10490         rsurface.passcolor4f_bufferoffset = 0;
10491         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10492         {
10493                 c2[0] = c[0] * r;
10494                 c2[1] = c[1] * g;
10495                 c2[2] = c[2] * b;
10496                 c2[3] = c[3] * a;
10497         }
10498 }
10499
10500 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10501 {
10502         int i;
10503         const float *c;
10504         float *c2;
10505         if (!rsurface.passcolor4f)
10506                 return;
10507         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10508         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10509         rsurface.passcolor4f_vertexbuffer = 0;
10510         rsurface.passcolor4f_bufferoffset = 0;
10511         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10512         {
10513                 c2[0] = c[0] + r_refdef.scene.ambient;
10514                 c2[1] = c[1] + r_refdef.scene.ambient;
10515                 c2[2] = c[2] + r_refdef.scene.ambient;
10516                 c2[3] = c[3];
10517         }
10518 }
10519
10520 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10521 {
10522         // TODO: optimize
10523         rsurface.passcolor4f = NULL;
10524         rsurface.passcolor4f_vertexbuffer = 0;
10525         rsurface.passcolor4f_bufferoffset = 0;
10526         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10527         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10528         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10529         GL_Color(r, g, b, a);
10530         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10531         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10532         R_Mesh_TexMatrix(0, NULL);
10533         RSurf_DrawBatch();
10534 }
10535
10536 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10537 {
10538         // TODO: optimize applyfog && applycolor case
10539         // just apply fog if necessary, and tint the fog color array if necessary
10540         rsurface.passcolor4f = NULL;
10541         rsurface.passcolor4f_vertexbuffer = 0;
10542         rsurface.passcolor4f_bufferoffset = 0;
10543         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10544         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10545         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10546         GL_Color(r, g, b, a);
10547         RSurf_DrawBatch();
10548 }
10549
10550 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10551 {
10552         // TODO: optimize
10553         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10554         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10555         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10556         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10557         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10558         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10559         GL_Color(r, g, b, a);
10560         RSurf_DrawBatch();
10561 }
10562
10563 static void RSurf_DrawBatch_GL11_ClampColor(void)
10564 {
10565         int i;
10566         const float *c1;
10567         float *c2;
10568         if (!rsurface.passcolor4f)
10569                 return;
10570         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10571         {
10572                 c2[0] = bound(0.0f, c1[0], 1.0f);
10573                 c2[1] = bound(0.0f, c1[1], 1.0f);
10574                 c2[2] = bound(0.0f, c1[2], 1.0f);
10575                 c2[3] = bound(0.0f, c1[3], 1.0f);
10576         }
10577 }
10578
10579 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10580 {
10581         int i;
10582         float f;
10583         const float *v;
10584         const float *n;
10585         float *c;
10586         //vec3_t eyedir;
10587
10588         // fake shading
10589         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10590         rsurface.passcolor4f_vertexbuffer = 0;
10591         rsurface.passcolor4f_bufferoffset = 0;
10592         for (i = 0, 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)
10593         {
10594                 f = -DotProduct(r_refdef.view.forward, n);
10595                 f = max(0, f);
10596                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10597                 f *= r_refdef.lightmapintensity;
10598                 Vector4Set(c, f, f, f, 1);
10599         }
10600 }
10601
10602 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10603 {
10604         RSurf_DrawBatch_GL11_ApplyFakeLight();
10605         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10606         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10607         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10608         GL_Color(r, g, b, a);
10609         RSurf_DrawBatch();
10610 }
10611
10612 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10613 {
10614         int i;
10615         float f;
10616         float alpha;
10617         const float *v;
10618         const float *n;
10619         float *c;
10620         vec3_t ambientcolor;
10621         vec3_t diffusecolor;
10622         vec3_t lightdir;
10623         // TODO: optimize
10624         // model lighting
10625         VectorCopy(rsurface.modellight_lightdir, lightdir);
10626         f = 0.5f * r_refdef.lightmapintensity;
10627         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10628         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10629         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10630         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10631         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10632         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10633         alpha = *a;
10634         if (VectorLength2(diffusecolor) > 0)
10635         {
10636                 // q3-style directional shading
10637                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10638                 rsurface.passcolor4f_vertexbuffer = 0;
10639                 rsurface.passcolor4f_bufferoffset = 0;
10640                 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)
10641                 {
10642                         if ((f = DotProduct(n, lightdir)) > 0)
10643                                 VectorMA(ambientcolor, f, diffusecolor, c);
10644                         else
10645                                 VectorCopy(ambientcolor, c);
10646                         c[3] = alpha;
10647                 }
10648                 *r = 1;
10649                 *g = 1;
10650                 *b = 1;
10651                 *a = 1;
10652                 *applycolor = false;
10653         }
10654         else
10655         {
10656                 *r = ambientcolor[0];
10657                 *g = ambientcolor[1];
10658                 *b = ambientcolor[2];
10659                 rsurface.passcolor4f = NULL;
10660                 rsurface.passcolor4f_vertexbuffer = 0;
10661                 rsurface.passcolor4f_bufferoffset = 0;
10662         }
10663 }
10664
10665 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10666 {
10667         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10668         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10669         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10670         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10671         GL_Color(r, g, b, a);
10672         RSurf_DrawBatch();
10673 }
10674
10675 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10676 {
10677         int i;
10678         float f;
10679         const float *v;
10680         float *c;
10681
10682         // fake shading
10683         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10684         rsurface.passcolor4f_vertexbuffer = 0;
10685         rsurface.passcolor4f_bufferoffset = 0;
10686
10687         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10688         {
10689                 f = 1 - RSurf_FogVertex(v);
10690                 c[0] = r;
10691                 c[1] = g;
10692                 c[2] = b;
10693                 c[3] = f * a;
10694         }
10695 }
10696
10697 void RSurf_SetupDepthAndCulling(void)
10698 {
10699         // submodels are biased to avoid z-fighting with world surfaces that they
10700         // may be exactly overlapping (avoids z-fighting artifacts on certain
10701         // doors and things in Quake maps)
10702         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10703         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10704         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10705         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10706 }
10707
10708 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10709 {
10710         // transparent sky would be ridiculous
10711         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10712                 return;
10713         R_SetupShader_Generic_NoTexture(false, false);
10714         skyrenderlater = true;
10715         RSurf_SetupDepthAndCulling();
10716         GL_DepthMask(true);
10717         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10718         // skymasking on them, and Quake3 never did sky masking (unlike
10719         // software Quake and software Quake2), so disable the sky masking
10720         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10721         // and skymasking also looks very bad when noclipping outside the
10722         // level, so don't use it then either.
10723         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10724         {
10725                 R_Mesh_ResetTextureState();
10726                 if (skyrendermasked)
10727                 {
10728                         R_SetupShader_DepthOrShadow(false, false, false);
10729                         // depth-only (masking)
10730                         GL_ColorMask(0,0,0,0);
10731                         // just to make sure that braindead drivers don't draw
10732                         // anything despite that colormask...
10733                         GL_BlendFunc(GL_ZERO, GL_ONE);
10734                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10735                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10736                 }
10737                 else
10738                 {
10739                         R_SetupShader_Generic_NoTexture(false, false);
10740                         // fog sky
10741                         GL_BlendFunc(GL_ONE, GL_ZERO);
10742                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10743                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10744                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10745                 }
10746                 RSurf_DrawBatch();
10747                 if (skyrendermasked)
10748                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10749         }
10750         R_Mesh_ResetTextureState();
10751         GL_Color(1, 1, 1, 1);
10752 }
10753
10754 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10755 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10756 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10757 {
10758         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10759                 return;
10760         if (prepass)
10761         {
10762                 // render screenspace normalmap to texture
10763                 GL_DepthMask(true);
10764                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10765                 RSurf_DrawBatch();
10766                 return;
10767         }
10768
10769         // bind lightmap texture
10770
10771         // water/refraction/reflection/camera surfaces have to be handled specially
10772         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10773         {
10774                 int start, end, startplaneindex;
10775                 for (start = 0;start < texturenumsurfaces;start = end)
10776                 {
10777                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10778                         if(startplaneindex < 0)
10779                         {
10780                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10781                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10782                                 end = start + 1;
10783                                 continue;
10784                         }
10785                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10786                                 ;
10787                         // now that we have a batch using the same planeindex, render it
10788                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10789                         {
10790                                 // render water or distortion background
10791                                 GL_DepthMask(true);
10792                                 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);
10793                                 RSurf_DrawBatch();
10794                                 // blend surface on top
10795                                 GL_DepthMask(false);
10796                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10797                                 RSurf_DrawBatch();
10798                         }
10799                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10800                         {
10801                                 // render surface with reflection texture as input
10802                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10803                                 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);
10804                                 RSurf_DrawBatch();
10805                         }
10806                 }
10807                 return;
10808         }
10809
10810         // render surface batch normally
10811         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10812         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);
10813         RSurf_DrawBatch();
10814 }
10815
10816 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10817 {
10818         // OpenGL 1.3 path - anything not completely ancient
10819         qboolean applycolor;
10820         qboolean applyfog;
10821         int layerindex;
10822         const texturelayer_t *layer;
10823         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);
10824         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10825
10826         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10827         {
10828                 vec4_t layercolor;
10829                 int layertexrgbscale;
10830                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10831                 {
10832                         if (layerindex == 0)
10833                                 GL_AlphaTest(true);
10834                         else
10835                         {
10836                                 GL_AlphaTest(false);
10837                                 GL_DepthFunc(GL_EQUAL);
10838                         }
10839                 }
10840                 GL_DepthMask(layer->depthmask && writedepth);
10841                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10842                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10843                 {
10844                         layertexrgbscale = 4;
10845                         VectorScale(layer->color, 0.25f, layercolor);
10846                 }
10847                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10848                 {
10849                         layertexrgbscale = 2;
10850                         VectorScale(layer->color, 0.5f, layercolor);
10851                 }
10852                 else
10853                 {
10854                         layertexrgbscale = 1;
10855                         VectorScale(layer->color, 1.0f, layercolor);
10856                 }
10857                 layercolor[3] = layer->color[3];
10858                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10859                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10860                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10861                 switch (layer->type)
10862                 {
10863                 case TEXTURELAYERTYPE_LITTEXTURE:
10864                         // single-pass lightmapped texture with 2x rgbscale
10865                         R_Mesh_TexBind(0, r_texture_white);
10866                         R_Mesh_TexMatrix(0, NULL);
10867                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10868                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10869                         R_Mesh_TexBind(1, layer->texture);
10870                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10871                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10873                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10874                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10875                         else if (FAKELIGHT_ENABLED)
10876                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10877                         else if (rsurface.uselightmaptexture)
10878                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10879                         else
10880                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10881                         break;
10882                 case TEXTURELAYERTYPE_TEXTURE:
10883                         // singletexture unlit texture with transparency support
10884                         R_Mesh_TexBind(0, layer->texture);
10885                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10886                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10887                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10888                         R_Mesh_TexBind(1, 0);
10889                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10890                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10891                         break;
10892                 case TEXTURELAYERTYPE_FOG:
10893                         // singletexture fogging
10894                         if (layer->texture)
10895                         {
10896                                 R_Mesh_TexBind(0, layer->texture);
10897                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10898                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10899                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10900                         }
10901                         else
10902                         {
10903                                 R_Mesh_TexBind(0, 0);
10904                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10905                         }
10906                         R_Mesh_TexBind(1, 0);
10907                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10908                         // generate a color array for the fog pass
10909                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10910                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10911                         RSurf_DrawBatch();
10912                         break;
10913                 default:
10914                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10915                 }
10916         }
10917         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10918         {
10919                 GL_DepthFunc(GL_LEQUAL);
10920                 GL_AlphaTest(false);
10921         }
10922 }
10923
10924 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10925 {
10926         // OpenGL 1.1 - crusty old voodoo path
10927         qboolean applyfog;
10928         int layerindex;
10929         const texturelayer_t *layer;
10930         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);
10931         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10932
10933         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10934         {
10935                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10936                 {
10937                         if (layerindex == 0)
10938                                 GL_AlphaTest(true);
10939                         else
10940                         {
10941                                 GL_AlphaTest(false);
10942                                 GL_DepthFunc(GL_EQUAL);
10943                         }
10944                 }
10945                 GL_DepthMask(layer->depthmask && writedepth);
10946                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10947                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10948                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10949                 switch (layer->type)
10950                 {
10951                 case TEXTURELAYERTYPE_LITTEXTURE:
10952                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10953                         {
10954                                 // two-pass lit texture with 2x rgbscale
10955                                 // first the lightmap pass
10956                                 R_Mesh_TexBind(0, r_texture_white);
10957                                 R_Mesh_TexMatrix(0, NULL);
10958                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10960                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10961                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10962                                 else if (FAKELIGHT_ENABLED)
10963                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10964                                 else if (rsurface.uselightmaptexture)
10965                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10966                                 else
10967                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10968                                 // then apply the texture to it
10969                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10970                                 R_Mesh_TexBind(0, layer->texture);
10971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10974                                 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);
10975                         }
10976                         else
10977                         {
10978                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10979                                 R_Mesh_TexBind(0, layer->texture);
10980                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10981                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10983                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10984                                         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);
10985                                 else if (FAKELIGHT_ENABLED)
10986                                         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);
10987                                 else
10988                                         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);
10989                         }
10990                         break;
10991                 case TEXTURELAYERTYPE_TEXTURE:
10992                         // singletexture unlit texture with transparency support
10993                         R_Mesh_TexBind(0, layer->texture);
10994                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10995                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10996                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10997                         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);
10998                         break;
10999                 case TEXTURELAYERTYPE_FOG:
11000                         // singletexture fogging
11001                         if (layer->texture)
11002                         {
11003                                 R_Mesh_TexBind(0, layer->texture);
11004                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11005                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11006                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11007                         }
11008                         else
11009                         {
11010                                 R_Mesh_TexBind(0, 0);
11011                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11012                         }
11013                         // generate a color array for the fog pass
11014                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11015                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11016                         RSurf_DrawBatch();
11017                         break;
11018                 default:
11019                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11020                 }
11021         }
11022         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11023         {
11024                 GL_DepthFunc(GL_LEQUAL);
11025                 GL_AlphaTest(false);
11026         }
11027 }
11028
11029 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11030 {
11031         int vi;
11032         int j;
11033         r_vertexgeneric_t *batchvertex;
11034         float c[4];
11035
11036 //      R_Mesh_ResetTextureState();
11037         R_SetupShader_Generic_NoTexture(false, false);
11038
11039         if(rsurface.texture && rsurface.texture->currentskinframe)
11040         {
11041                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11042                 c[3] *= rsurface.texture->currentalpha;
11043         }
11044         else
11045         {
11046                 c[0] = 1;
11047                 c[1] = 0;
11048                 c[2] = 1;
11049                 c[3] = 1;
11050         }
11051
11052         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11053         {
11054                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11055                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11056                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11057         }
11058
11059         // brighten it up (as texture value 127 means "unlit")
11060         c[0] *= 2 * r_refdef.view.colorscale;
11061         c[1] *= 2 * r_refdef.view.colorscale;
11062         c[2] *= 2 * r_refdef.view.colorscale;
11063
11064         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11065                 c[3] *= r_wateralpha.value;
11066
11067         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11068         {
11069                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11070                 GL_DepthMask(false);
11071         }
11072         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11073         {
11074                 GL_BlendFunc(GL_ONE, GL_ONE);
11075                 GL_DepthMask(false);
11076         }
11077         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11078         {
11079                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11080                 GL_DepthMask(false);
11081         }
11082         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11083         {
11084                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11085                 GL_DepthMask(false);
11086         }
11087         else
11088         {
11089                 GL_BlendFunc(GL_ONE, GL_ZERO);
11090                 GL_DepthMask(writedepth);
11091         }
11092
11093         if (r_showsurfaces.integer == 3)
11094         {
11095                 rsurface.passcolor4f = NULL;
11096
11097                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11098                 {
11099                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11100
11101                         rsurface.passcolor4f = NULL;
11102                         rsurface.passcolor4f_vertexbuffer = 0;
11103                         rsurface.passcolor4f_bufferoffset = 0;
11104                 }
11105                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11106                 {
11107                         qboolean applycolor = true;
11108                         float one = 1.0;
11109
11110                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11111
11112                         r_refdef.lightmapintensity = 1;
11113                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11114                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11115                 }
11116                 else if (FAKELIGHT_ENABLED)
11117                 {
11118                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11119
11120                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11121                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11122                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11123                 }
11124                 else
11125                 {
11126                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11127
11128                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11129                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11130                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11131                 }
11132
11133                 if(!rsurface.passcolor4f)
11134                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11135
11136                 RSurf_DrawBatch_GL11_ApplyAmbient();
11137                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11138                 if(r_refdef.fogenabled)
11139                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11140                 RSurf_DrawBatch_GL11_ClampColor();
11141
11142                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11143                 R_SetupShader_Generic_NoTexture(false, false);
11144                 RSurf_DrawBatch();
11145         }
11146         else if (!r_refdef.view.showdebug)
11147         {
11148                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11149                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11150                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11151                 {
11152                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11153                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11154                 }
11155                 R_Mesh_PrepareVertices_Generic_Unlock();
11156                 RSurf_DrawBatch();
11157         }
11158         else if (r_showsurfaces.integer == 4)
11159         {
11160                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11161                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11162                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11163                 {
11164                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11165                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11166                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11167                 }
11168                 R_Mesh_PrepareVertices_Generic_Unlock();
11169                 RSurf_DrawBatch();
11170         }
11171         else if (r_showsurfaces.integer == 2)
11172         {
11173                 const int *e;
11174                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11175                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11176                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11177                 {
11178                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11179                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11180                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11181                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11182                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11183                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11184                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11185                 }
11186                 R_Mesh_PrepareVertices_Generic_Unlock();
11187                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11188         }
11189         else
11190         {
11191                 int texturesurfaceindex;
11192                 int k;
11193                 const msurface_t *surface;
11194                 float surfacecolor4f[4];
11195                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11196                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11197                 vi = 0;
11198                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11199                 {
11200                         surface = texturesurfacelist[texturesurfaceindex];
11201                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11202                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11203                         for (j = 0;j < surface->num_vertices;j++)
11204                         {
11205                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11206                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11207                                 vi++;
11208                         }
11209                 }
11210                 R_Mesh_PrepareVertices_Generic_Unlock();
11211                 RSurf_DrawBatch();
11212         }
11213 }
11214
11215 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11216 {
11217         CHECKGLERROR
11218         RSurf_SetupDepthAndCulling();
11219         if (r_showsurfaces.integer)
11220         {
11221                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11222                 return;
11223         }
11224         switch (vid.renderpath)
11225         {
11226         case RENDERPATH_GL20:
11227         case RENDERPATH_D3D9:
11228         case RENDERPATH_D3D10:
11229         case RENDERPATH_D3D11:
11230         case RENDERPATH_SOFT:
11231         case RENDERPATH_GLES2:
11232                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11233                 break;
11234         case RENDERPATH_GL13:
11235         case RENDERPATH_GLES1:
11236                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11237                 break;
11238         case RENDERPATH_GL11:
11239                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11240                 break;
11241         }
11242         CHECKGLERROR
11243 }
11244
11245 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11246 {
11247         CHECKGLERROR
11248         RSurf_SetupDepthAndCulling();
11249         if (r_showsurfaces.integer)
11250         {
11251                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11252                 return;
11253         }
11254         switch (vid.renderpath)
11255         {
11256         case RENDERPATH_GL20:
11257         case RENDERPATH_D3D9:
11258         case RENDERPATH_D3D10:
11259         case RENDERPATH_D3D11:
11260         case RENDERPATH_SOFT:
11261         case RENDERPATH_GLES2:
11262                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11263                 break;
11264         case RENDERPATH_GL13:
11265         case RENDERPATH_GLES1:
11266                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11267                 break;
11268         case RENDERPATH_GL11:
11269                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11270                 break;
11271         }
11272         CHECKGLERROR
11273 }
11274
11275 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11276 {
11277         int i, j;
11278         int texturenumsurfaces, endsurface;
11279         texture_t *texture;
11280         const msurface_t *surface;
11281         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11282
11283         // if the model is static it doesn't matter what value we give for
11284         // wantnormals and wanttangents, so this logic uses only rules applicable
11285         // to a model, knowing that they are meaningless otherwise
11286         if (ent == r_refdef.scene.worldentity)
11287                 RSurf_ActiveWorldEntity();
11288         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11289                 RSurf_ActiveModelEntity(ent, false, false, false);
11290         else
11291         {
11292                 switch (vid.renderpath)
11293                 {
11294                 case RENDERPATH_GL20:
11295                 case RENDERPATH_D3D9:
11296                 case RENDERPATH_D3D10:
11297                 case RENDERPATH_D3D11:
11298                 case RENDERPATH_SOFT:
11299                 case RENDERPATH_GLES2:
11300                         RSurf_ActiveModelEntity(ent, true, true, false);
11301                         break;
11302                 case RENDERPATH_GL11:
11303                 case RENDERPATH_GL13:
11304                 case RENDERPATH_GLES1:
11305                         RSurf_ActiveModelEntity(ent, true, false, false);
11306                         break;
11307                 }
11308         }
11309
11310         if (r_transparentdepthmasking.integer)
11311         {
11312                 qboolean setup = false;
11313                 for (i = 0;i < numsurfaces;i = j)
11314                 {
11315                         j = i + 1;
11316                         surface = rsurface.modelsurfaces + surfacelist[i];
11317                         texture = surface->texture;
11318                         rsurface.texture = R_GetCurrentTexture(texture);
11319                         rsurface.lightmaptexture = NULL;
11320                         rsurface.deluxemaptexture = NULL;
11321                         rsurface.uselightmaptexture = false;
11322                         // scan ahead until we find a different texture
11323                         endsurface = min(i + 1024, numsurfaces);
11324                         texturenumsurfaces = 0;
11325                         texturesurfacelist[texturenumsurfaces++] = surface;
11326                         for (;j < endsurface;j++)
11327                         {
11328                                 surface = rsurface.modelsurfaces + surfacelist[j];
11329                                 if (texture != surface->texture)
11330                                         break;
11331                                 texturesurfacelist[texturenumsurfaces++] = surface;
11332                         }
11333                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11334                                 continue;
11335                         // render the range of surfaces as depth
11336                         if (!setup)
11337                         {
11338                                 setup = true;
11339                                 GL_ColorMask(0,0,0,0);
11340                                 GL_Color(1,1,1,1);
11341                                 GL_DepthTest(true);
11342                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11343                                 GL_DepthMask(true);
11344 //                              R_Mesh_ResetTextureState();
11345                         }
11346                         RSurf_SetupDepthAndCulling();
11347                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11348                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11349                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11350                         RSurf_DrawBatch();
11351                 }
11352                 if (setup)
11353                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11354         }
11355
11356         for (i = 0;i < numsurfaces;i = j)
11357         {
11358                 j = i + 1;
11359                 surface = rsurface.modelsurfaces + surfacelist[i];
11360                 texture = surface->texture;
11361                 rsurface.texture = R_GetCurrentTexture(texture);
11362                 // scan ahead until we find a different texture
11363                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11364                 texturenumsurfaces = 0;
11365                 texturesurfacelist[texturenumsurfaces++] = surface;
11366                 if(FAKELIGHT_ENABLED)
11367                 {
11368                         rsurface.lightmaptexture = NULL;
11369                         rsurface.deluxemaptexture = NULL;
11370                         rsurface.uselightmaptexture = false;
11371                         for (;j < endsurface;j++)
11372                         {
11373                                 surface = rsurface.modelsurfaces + surfacelist[j];
11374                                 if (texture != surface->texture)
11375                                         break;
11376                                 texturesurfacelist[texturenumsurfaces++] = surface;
11377                         }
11378                 }
11379                 else
11380                 {
11381                         rsurface.lightmaptexture = surface->lightmaptexture;
11382                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11383                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11384                         for (;j < endsurface;j++)
11385                         {
11386                                 surface = rsurface.modelsurfaces + surfacelist[j];
11387                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11388                                         break;
11389                                 texturesurfacelist[texturenumsurfaces++] = surface;
11390                         }
11391                 }
11392                 // render the range of surfaces
11393                 if (ent == r_refdef.scene.worldentity)
11394                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11395                 else
11396                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11397         }
11398         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11399 }
11400
11401 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11402 {
11403         // transparent surfaces get pushed off into the transparent queue
11404         int surfacelistindex;
11405         const msurface_t *surface;
11406         vec3_t tempcenter, center;
11407         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11408         {
11409                 surface = texturesurfacelist[surfacelistindex];
11410                 if (r_transparent_sortsurfacesbynearest.integer)
11411                 {
11412                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11413                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11414                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11415                 }
11416                 else
11417                 {
11418                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11419                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11420                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11421                 }
11422                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11423                 if (rsurface.entity->transparent_offset) // transparent offset
11424                 {
11425                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11426                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11427                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11428                 }
11429                 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);
11430         }
11431 }
11432
11433 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11434 {
11435         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11436                 return;
11437         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11438                 return;
11439         RSurf_SetupDepthAndCulling();
11440         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11441         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11442         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11443         RSurf_DrawBatch();
11444 }
11445
11446 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11447 {
11448         CHECKGLERROR
11449         if (depthonly)
11450                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11451         else if (prepass)
11452         {
11453                 if (!rsurface.texture->currentnumlayers)
11454                         return;
11455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11456                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11457                 else
11458                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11459         }
11460         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11461                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11462         else if (!rsurface.texture->currentnumlayers)
11463                 return;
11464         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11465         {
11466                 // in the deferred case, transparent surfaces were queued during prepass
11467                 if (!r_shadow_usingdeferredprepass)
11468                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11469         }
11470         else
11471         {
11472                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11473                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11474         }
11475         CHECKGLERROR
11476 }
11477
11478 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11479 {
11480         int i, j;
11481         texture_t *texture;
11482         R_FrameData_SetMark();
11483         // break the surface list down into batches by texture and use of lightmapping
11484         for (i = 0;i < numsurfaces;i = j)
11485         {
11486                 j = i + 1;
11487                 // texture is the base texture pointer, rsurface.texture is the
11488                 // current frame/skin the texture is directing us to use (for example
11489                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11490                 // use skin 1 instead)
11491                 texture = surfacelist[i]->texture;
11492                 rsurface.texture = R_GetCurrentTexture(texture);
11493                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11494                 {
11495                         // if this texture is not the kind we want, skip ahead to the next one
11496                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11497                                 ;
11498                         continue;
11499                 }
11500                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11501                 {
11502                         rsurface.lightmaptexture = NULL;
11503                         rsurface.deluxemaptexture = NULL;
11504                         rsurface.uselightmaptexture = false;
11505                         // simply scan ahead until we find a different texture or lightmap state
11506                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11507                                 ;
11508                 }
11509                 else
11510                 {
11511                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11512                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11513                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11514                         // simply scan ahead until we find a different texture or lightmap state
11515                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11516                                 ;
11517                 }
11518                 // render the range of surfaces
11519                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11520         }
11521         R_FrameData_ReturnToMark();
11522 }
11523
11524 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11525 {
11526         CHECKGLERROR
11527         if (depthonly)
11528                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11529         else if (prepass)
11530         {
11531                 if (!rsurface.texture->currentnumlayers)
11532                         return;
11533                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11534                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11535                 else
11536                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11537         }
11538         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11539                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11540         else if (!rsurface.texture->currentnumlayers)
11541                 return;
11542         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11543         {
11544                 // in the deferred case, transparent surfaces were queued during prepass
11545                 if (!r_shadow_usingdeferredprepass)
11546                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11547         }
11548         else
11549         {
11550                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11551                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11552         }
11553         CHECKGLERROR
11554 }
11555
11556 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11557 {
11558         int i, j;
11559         texture_t *texture;
11560         R_FrameData_SetMark();
11561         // break the surface list down into batches by texture and use of lightmapping
11562         for (i = 0;i < numsurfaces;i = j)
11563         {
11564                 j = i + 1;
11565                 // texture is the base texture pointer, rsurface.texture is the
11566                 // current frame/skin the texture is directing us to use (for example
11567                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11568                 // use skin 1 instead)
11569                 texture = surfacelist[i]->texture;
11570                 rsurface.texture = R_GetCurrentTexture(texture);
11571                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11572                 {
11573                         // if this texture is not the kind we want, skip ahead to the next one
11574                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11575                                 ;
11576                         continue;
11577                 }
11578                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11579                 {
11580                         rsurface.lightmaptexture = NULL;
11581                         rsurface.deluxemaptexture = NULL;
11582                         rsurface.uselightmaptexture = false;
11583                         // simply scan ahead until we find a different texture or lightmap state
11584                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11585                                 ;
11586                 }
11587                 else
11588                 {
11589                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11590                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11591                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11592                         // simply scan ahead until we find a different texture or lightmap state
11593                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11594                                 ;
11595                 }
11596                 // render the range of surfaces
11597                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11598         }
11599         R_FrameData_ReturnToMark();
11600 }
11601
11602 float locboxvertex3f[6*4*3] =
11603 {
11604         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11605         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11606         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11607         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11608         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11609         1,0,0, 0,0,0, 0,1,0, 1,1,0
11610 };
11611
11612 unsigned short locboxelements[6*2*3] =
11613 {
11614          0, 1, 2, 0, 2, 3,
11615          4, 5, 6, 4, 6, 7,
11616          8, 9,10, 8,10,11,
11617         12,13,14, 12,14,15,
11618         16,17,18, 16,18,19,
11619         20,21,22, 20,22,23
11620 };
11621
11622 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11623 {
11624         int i, j;
11625         cl_locnode_t *loc = (cl_locnode_t *)ent;
11626         vec3_t mins, size;
11627         float vertex3f[6*4*3];
11628         CHECKGLERROR
11629         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11630         GL_DepthMask(false);
11631         GL_DepthRange(0, 1);
11632         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11633         GL_DepthTest(true);
11634         GL_CullFace(GL_NONE);
11635         R_EntityMatrix(&identitymatrix);
11636
11637 //      R_Mesh_ResetTextureState();
11638
11639         i = surfacelist[0];
11640         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11641                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11642                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11643                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11644
11645         if (VectorCompare(loc->mins, loc->maxs))
11646         {
11647                 VectorSet(size, 2, 2, 2);
11648                 VectorMA(loc->mins, -0.5f, size, mins);
11649         }
11650         else
11651         {
11652                 VectorCopy(loc->mins, mins);
11653                 VectorSubtract(loc->maxs, loc->mins, size);
11654         }
11655
11656         for (i = 0;i < 6*4*3;)
11657                 for (j = 0;j < 3;j++, i++)
11658                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11659
11660         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11661         R_SetupShader_Generic_NoTexture(false, false);
11662         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11663 }
11664
11665 void R_DrawLocs(void)
11666 {
11667         int index;
11668         cl_locnode_t *loc, *nearestloc;
11669         vec3_t center;
11670         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11671         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11672         {
11673                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11674                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11675         }
11676 }
11677
11678 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11679 {
11680         if (decalsystem->decals)
11681                 Mem_Free(decalsystem->decals);
11682         memset(decalsystem, 0, sizeof(*decalsystem));
11683 }
11684
11685 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)
11686 {
11687         tridecal_t *decal;
11688         tridecal_t *decals;
11689         int i;
11690
11691         // expand or initialize the system
11692         if (decalsystem->maxdecals <= decalsystem->numdecals)
11693         {
11694                 decalsystem_t old = *decalsystem;
11695                 qboolean useshortelements;
11696                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11697                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11698                 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)));
11699                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11700                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11701                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11702                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11703                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11704                 if (decalsystem->numdecals)
11705                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11706                 if (old.decals)
11707                         Mem_Free(old.decals);
11708                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11709                         decalsystem->element3i[i] = i;
11710                 if (useshortelements)
11711                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11712                                 decalsystem->element3s[i] = i;
11713         }
11714
11715         // grab a decal and search for another free slot for the next one
11716         decals = decalsystem->decals;
11717         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11718         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11719                 ;
11720         decalsystem->freedecal = i;
11721         if (decalsystem->numdecals <= i)
11722                 decalsystem->numdecals = i + 1;
11723
11724         // initialize the decal
11725         decal->lived = 0;
11726         decal->triangleindex = triangleindex;
11727         decal->surfaceindex = surfaceindex;
11728         decal->decalsequence = decalsequence;
11729         decal->color4f[0][0] = c0[0];
11730         decal->color4f[0][1] = c0[1];
11731         decal->color4f[0][2] = c0[2];
11732         decal->color4f[0][3] = 1;
11733         decal->color4f[1][0] = c1[0];
11734         decal->color4f[1][1] = c1[1];
11735         decal->color4f[1][2] = c1[2];
11736         decal->color4f[1][3] = 1;
11737         decal->color4f[2][0] = c2[0];
11738         decal->color4f[2][1] = c2[1];
11739         decal->color4f[2][2] = c2[2];
11740         decal->color4f[2][3] = 1;
11741         decal->vertex3f[0][0] = v0[0];
11742         decal->vertex3f[0][1] = v0[1];
11743         decal->vertex3f[0][2] = v0[2];
11744         decal->vertex3f[1][0] = v1[0];
11745         decal->vertex3f[1][1] = v1[1];
11746         decal->vertex3f[1][2] = v1[2];
11747         decal->vertex3f[2][0] = v2[0];
11748         decal->vertex3f[2][1] = v2[1];
11749         decal->vertex3f[2][2] = v2[2];
11750         decal->texcoord2f[0][0] = t0[0];
11751         decal->texcoord2f[0][1] = t0[1];
11752         decal->texcoord2f[1][0] = t1[0];
11753         decal->texcoord2f[1][1] = t1[1];
11754         decal->texcoord2f[2][0] = t2[0];
11755         decal->texcoord2f[2][1] = t2[1];
11756         TriangleNormal(v0, v1, v2, decal->plane);
11757         VectorNormalize(decal->plane);
11758         decal->plane[3] = DotProduct(v0, decal->plane);
11759 }
11760
11761 extern cvar_t cl_decals_bias;
11762 extern cvar_t cl_decals_models;
11763 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11764 // baseparms, parms, temps
11765 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)
11766 {
11767         int cornerindex;
11768         int index;
11769         float v[9][3];
11770         const float *vertex3f;
11771         const float *normal3f;
11772         int numpoints;
11773         float points[2][9][3];
11774         float temp[3];
11775         float tc[9][2];
11776         float f;
11777         float c[9][4];
11778         const int *e;
11779
11780         e = rsurface.modelelement3i + 3*triangleindex;
11781
11782         vertex3f = rsurface.modelvertex3f;
11783         normal3f = rsurface.modelnormal3f;
11784
11785         if (normal3f)
11786         {
11787                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11788                 {
11789                         index = 3*e[cornerindex];
11790                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11791                 }
11792         }
11793         else
11794         {
11795                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11796                 {
11797                         index = 3*e[cornerindex];
11798                         VectorCopy(vertex3f + index, v[cornerindex]);
11799                 }
11800         }
11801
11802         // cull backfaces
11803         //TriangleNormal(v[0], v[1], v[2], normal);
11804         //if (DotProduct(normal, localnormal) < 0.0f)
11805         //      continue;
11806         // clip by each of the box planes formed from the projection matrix
11807         // if anything survives, we emit the decal
11808         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]);
11809         if (numpoints < 3)
11810                 return;
11811         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]);
11812         if (numpoints < 3)
11813                 return;
11814         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]);
11815         if (numpoints < 3)
11816                 return;
11817         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]);
11818         if (numpoints < 3)
11819                 return;
11820         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]);
11821         if (numpoints < 3)
11822                 return;
11823         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]);
11824         if (numpoints < 3)
11825                 return;
11826         // some part of the triangle survived, so we have to accept it...
11827         if (dynamic)
11828         {
11829                 // dynamic always uses the original triangle
11830                 numpoints = 3;
11831                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11832                 {
11833                         index = 3*e[cornerindex];
11834                         VectorCopy(vertex3f + index, v[cornerindex]);
11835                 }
11836         }
11837         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11838         {
11839                 // convert vertex positions to texcoords
11840                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11841                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11842                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11843                 // calculate distance fade from the projection origin
11844                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11845                 f = bound(0.0f, f, 1.0f);
11846                 c[cornerindex][0] = r * f;
11847                 c[cornerindex][1] = g * f;
11848                 c[cornerindex][2] = b * f;
11849                 c[cornerindex][3] = 1.0f;
11850                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11851         }
11852         if (dynamic)
11853                 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);
11854         else
11855                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11856                         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);
11857 }
11858 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)
11859 {
11860         matrix4x4_t projection;
11861         decalsystem_t *decalsystem;
11862         qboolean dynamic;
11863         dp_model_t *model;
11864         const msurface_t *surface;
11865         const msurface_t *surfaces;
11866         const int *surfacelist;
11867         const texture_t *texture;
11868         int numtriangles;
11869         int numsurfacelist;
11870         int surfacelistindex;
11871         int surfaceindex;
11872         int triangleindex;
11873         float localorigin[3];
11874         float localnormal[3];
11875         float localmins[3];
11876         float localmaxs[3];
11877         float localsize;
11878         //float normal[3];
11879         float planes[6][4];
11880         float angles[3];
11881         bih_t *bih;
11882         int bih_triangles_count;
11883         int bih_triangles[256];
11884         int bih_surfaces[256];
11885
11886         decalsystem = &ent->decalsystem;
11887         model = ent->model;
11888         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11889         {
11890                 R_DecalSystem_Reset(&ent->decalsystem);
11891                 return;
11892         }
11893
11894         if (!model->brush.data_leafs && !cl_decals_models.integer)
11895         {
11896                 if (decalsystem->model)
11897                         R_DecalSystem_Reset(decalsystem);
11898                 return;
11899         }
11900
11901         if (decalsystem->model != model)
11902                 R_DecalSystem_Reset(decalsystem);
11903         decalsystem->model = model;
11904
11905         RSurf_ActiveModelEntity(ent, true, false, false);
11906
11907         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11908         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11909         VectorNormalize(localnormal);
11910         localsize = worldsize*rsurface.inversematrixscale;
11911         localmins[0] = localorigin[0] - localsize;
11912         localmins[1] = localorigin[1] - localsize;
11913         localmins[2] = localorigin[2] - localsize;
11914         localmaxs[0] = localorigin[0] + localsize;
11915         localmaxs[1] = localorigin[1] + localsize;
11916         localmaxs[2] = localorigin[2] + localsize;
11917
11918         //VectorCopy(localnormal, planes[4]);
11919         //VectorVectors(planes[4], planes[2], planes[0]);
11920         AnglesFromVectors(angles, localnormal, NULL, false);
11921         AngleVectors(angles, planes[0], planes[2], planes[4]);
11922         VectorNegate(planes[0], planes[1]);
11923         VectorNegate(planes[2], planes[3]);
11924         VectorNegate(planes[4], planes[5]);
11925         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11926         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11927         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11928         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11929         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11930         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11931
11932 #if 1
11933 // works
11934 {
11935         matrix4x4_t forwardprojection;
11936         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11937         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11938 }
11939 #else
11940 // broken
11941 {
11942         float projectionvector[4][3];
11943         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11944         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11945         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11946         projectionvector[0][0] = planes[0][0] * ilocalsize;
11947         projectionvector[0][1] = planes[1][0] * ilocalsize;
11948         projectionvector[0][2] = planes[2][0] * ilocalsize;
11949         projectionvector[1][0] = planes[0][1] * ilocalsize;
11950         projectionvector[1][1] = planes[1][1] * ilocalsize;
11951         projectionvector[1][2] = planes[2][1] * ilocalsize;
11952         projectionvector[2][0] = planes[0][2] * ilocalsize;
11953         projectionvector[2][1] = planes[1][2] * ilocalsize;
11954         projectionvector[2][2] = planes[2][2] * ilocalsize;
11955         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11956         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11957         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11958         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11959 }
11960 #endif
11961
11962         dynamic = model->surfmesh.isanimated;
11963         numsurfacelist = model->nummodelsurfaces;
11964         surfacelist = model->sortedmodelsurfaces;
11965         surfaces = model->data_surfaces;
11966
11967         bih = NULL;
11968         bih_triangles_count = -1;
11969         if(!dynamic)
11970         {
11971                 if(model->render_bih.numleafs)
11972                         bih = &model->render_bih;
11973                 else if(model->collision_bih.numleafs)
11974                         bih = &model->collision_bih;
11975         }
11976         if(bih)
11977                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11978         if(bih_triangles_count == 0)
11979                 return;
11980         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11981                 return;
11982         if(bih_triangles_count > 0)
11983         {
11984                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11985                 {
11986                         surfaceindex = bih_surfaces[triangleindex];
11987                         surface = surfaces + surfaceindex;
11988                         texture = surface->texture;
11989                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11990                                 continue;
11991                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11992                                 continue;
11993                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11994                 }
11995         }
11996         else
11997         {
11998                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11999                 {
12000                         surfaceindex = surfacelist[surfacelistindex];
12001                         surface = surfaces + surfaceindex;
12002                         // check cull box first because it rejects more than any other check
12003                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12004                                 continue;
12005                         // skip transparent surfaces
12006                         texture = surface->texture;
12007                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12008                                 continue;
12009                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12010                                 continue;
12011                         numtriangles = surface->num_triangles;
12012                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12013                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12014                 }
12015         }
12016 }
12017
12018 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12019 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)
12020 {
12021         int renderentityindex;
12022         float worldmins[3];
12023         float worldmaxs[3];
12024         entity_render_t *ent;
12025
12026         if (!cl_decals_newsystem.integer)
12027                 return;
12028
12029         worldmins[0] = worldorigin[0] - worldsize;
12030         worldmins[1] = worldorigin[1] - worldsize;
12031         worldmins[2] = worldorigin[2] - worldsize;
12032         worldmaxs[0] = worldorigin[0] + worldsize;
12033         worldmaxs[1] = worldorigin[1] + worldsize;
12034         worldmaxs[2] = worldorigin[2] + worldsize;
12035
12036         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12037
12038         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12039         {
12040                 ent = r_refdef.scene.entities[renderentityindex];
12041                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12042                         continue;
12043
12044                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12045         }
12046 }
12047
12048 typedef struct r_decalsystem_splatqueue_s
12049 {
12050         vec3_t worldorigin;
12051         vec3_t worldnormal;
12052         float color[4];
12053         float tcrange[4];
12054         float worldsize;
12055         unsigned int decalsequence;
12056 }
12057 r_decalsystem_splatqueue_t;
12058
12059 int r_decalsystem_numqueued = 0;
12060 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12061
12062 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)
12063 {
12064         r_decalsystem_splatqueue_t *queue;
12065
12066         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12067                 return;
12068
12069         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12070         VectorCopy(worldorigin, queue->worldorigin);
12071         VectorCopy(worldnormal, queue->worldnormal);
12072         Vector4Set(queue->color, r, g, b, a);
12073         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12074         queue->worldsize = worldsize;
12075         queue->decalsequence = cl.decalsequence++;
12076 }
12077
12078 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12079 {
12080         int i;
12081         r_decalsystem_splatqueue_t *queue;
12082
12083         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12084                 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);
12085         r_decalsystem_numqueued = 0;
12086 }
12087
12088 extern cvar_t cl_decals_max;
12089 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12090 {
12091         int i;
12092         decalsystem_t *decalsystem = &ent->decalsystem;
12093         int numdecals;
12094         unsigned int killsequence;
12095         tridecal_t *decal;
12096         float frametime;
12097         float lifetime;
12098
12099         if (!decalsystem->numdecals)
12100                 return;
12101
12102         if (r_showsurfaces.integer)
12103                 return;
12104
12105         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12106         {
12107                 R_DecalSystem_Reset(decalsystem);
12108                 return;
12109         }
12110
12111         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12112         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12113
12114         if (decalsystem->lastupdatetime)
12115                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12116         else
12117                 frametime = 0;
12118         decalsystem->lastupdatetime = r_refdef.scene.time;
12119         numdecals = decalsystem->numdecals;
12120
12121         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12122         {
12123                 if (decal->color4f[0][3])
12124                 {
12125                         decal->lived += frametime;
12126                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12127                         {
12128                                 memset(decal, 0, sizeof(*decal));
12129                                 if (decalsystem->freedecal > i)
12130                                         decalsystem->freedecal = i;
12131                         }
12132                 }
12133         }
12134         decal = decalsystem->decals;
12135         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12136                 numdecals--;
12137
12138         // collapse the array by shuffling the tail decals into the gaps
12139         for (;;)
12140         {
12141                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12142                         decalsystem->freedecal++;
12143                 if (decalsystem->freedecal == numdecals)
12144                         break;
12145                 decal[decalsystem->freedecal] = decal[--numdecals];
12146         }
12147
12148         decalsystem->numdecals = numdecals;
12149
12150         if (numdecals <= 0)
12151         {
12152                 // if there are no decals left, reset decalsystem
12153                 R_DecalSystem_Reset(decalsystem);
12154         }
12155 }
12156
12157 extern skinframe_t *decalskinframe;
12158 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12159 {
12160         int i;
12161         decalsystem_t *decalsystem = &ent->decalsystem;
12162         int numdecals;
12163         tridecal_t *decal;
12164         float faderate;
12165         float alpha;
12166         float *v3f;
12167         float *c4f;
12168         float *t2f;
12169         const int *e;
12170         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12171         int numtris = 0;
12172
12173         numdecals = decalsystem->numdecals;
12174         if (!numdecals)
12175                 return;
12176
12177         if (r_showsurfaces.integer)
12178                 return;
12179
12180         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12181         {
12182                 R_DecalSystem_Reset(decalsystem);
12183                 return;
12184         }
12185
12186         // if the model is static it doesn't matter what value we give for
12187         // wantnormals and wanttangents, so this logic uses only rules applicable
12188         // to a model, knowing that they are meaningless otherwise
12189         if (ent == r_refdef.scene.worldentity)
12190                 RSurf_ActiveWorldEntity();
12191         else
12192                 RSurf_ActiveModelEntity(ent, false, false, false);
12193
12194         decalsystem->lastupdatetime = r_refdef.scene.time;
12195
12196         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12197
12198         // update vertex positions for animated models
12199         v3f = decalsystem->vertex3f;
12200         c4f = decalsystem->color4f;
12201         t2f = decalsystem->texcoord2f;
12202         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12203         {
12204                 if (!decal->color4f[0][3])
12205                         continue;
12206
12207                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12208                         continue;
12209
12210                 // skip backfaces
12211                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12212                         continue;
12213
12214                 // update color values for fading decals
12215                 if (decal->lived >= cl_decals_time.value)
12216                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12217                 else
12218                         alpha = 1.0f;
12219
12220                 c4f[ 0] = decal->color4f[0][0] * alpha;
12221                 c4f[ 1] = decal->color4f[0][1] * alpha;
12222                 c4f[ 2] = decal->color4f[0][2] * alpha;
12223                 c4f[ 3] = 1;
12224                 c4f[ 4] = decal->color4f[1][0] * alpha;
12225                 c4f[ 5] = decal->color4f[1][1] * alpha;
12226                 c4f[ 6] = decal->color4f[1][2] * alpha;
12227                 c4f[ 7] = 1;
12228                 c4f[ 8] = decal->color4f[2][0] * alpha;
12229                 c4f[ 9] = decal->color4f[2][1] * alpha;
12230                 c4f[10] = decal->color4f[2][2] * alpha;
12231                 c4f[11] = 1;
12232
12233                 t2f[0] = decal->texcoord2f[0][0];
12234                 t2f[1] = decal->texcoord2f[0][1];
12235                 t2f[2] = decal->texcoord2f[1][0];
12236                 t2f[3] = decal->texcoord2f[1][1];
12237                 t2f[4] = decal->texcoord2f[2][0];
12238                 t2f[5] = decal->texcoord2f[2][1];
12239
12240                 // update vertex positions for animated models
12241                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12242                 {
12243                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12244                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12245                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12246                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12247                 }
12248                 else
12249                 {
12250                         VectorCopy(decal->vertex3f[0], v3f);
12251                         VectorCopy(decal->vertex3f[1], v3f + 3);
12252                         VectorCopy(decal->vertex3f[2], v3f + 6);
12253                 }
12254
12255                 if (r_refdef.fogenabled)
12256                 {
12257                         alpha = RSurf_FogVertex(v3f);
12258                         VectorScale(c4f, alpha, c4f);
12259                         alpha = RSurf_FogVertex(v3f + 3);
12260                         VectorScale(c4f + 4, alpha, c4f + 4);
12261                         alpha = RSurf_FogVertex(v3f + 6);
12262                         VectorScale(c4f + 8, alpha, c4f + 8);
12263                 }
12264
12265                 v3f += 9;
12266                 c4f += 12;
12267                 t2f += 6;
12268                 numtris++;
12269         }
12270
12271         if (numtris > 0)
12272         {
12273                 r_refdef.stats[r_stat_drawndecals] += numtris;
12274
12275                 // now render the decals all at once
12276                 // (this assumes they all use one particle font texture!)
12277                 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);
12278 //              R_Mesh_ResetTextureState();
12279                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12280                 GL_DepthMask(false);
12281                 GL_DepthRange(0, 1);
12282                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12283                 GL_DepthTest(true);
12284                 GL_CullFace(GL_NONE);
12285                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12286                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12287                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12288         }
12289 }
12290
12291 static void R_DrawModelDecals(void)
12292 {
12293         int i, numdecals;
12294
12295         // fade faster when there are too many decals
12296         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12297         for (i = 0;i < r_refdef.scene.numentities;i++)
12298                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12299
12300         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12301         for (i = 0;i < r_refdef.scene.numentities;i++)
12302                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12303                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12304
12305         R_DecalSystem_ApplySplatEntitiesQueue();
12306
12307         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12308         for (i = 0;i < r_refdef.scene.numentities;i++)
12309                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12310
12311         r_refdef.stats[r_stat_totaldecals] += numdecals;
12312
12313         if (r_showsurfaces.integer)
12314                 return;
12315
12316         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12317
12318         for (i = 0;i < r_refdef.scene.numentities;i++)
12319         {
12320                 if (!r_refdef.viewcache.entityvisible[i])
12321                         continue;
12322                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12323                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12324         }
12325 }
12326
12327 extern cvar_t mod_collision_bih;
12328 static void R_DrawDebugModel(void)
12329 {
12330         entity_render_t *ent = rsurface.entity;
12331         int i, j, flagsmask;
12332         const msurface_t *surface;
12333         dp_model_t *model = ent->model;
12334
12335         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12336                 return;
12337
12338         if (r_showoverdraw.value > 0)
12339         {
12340                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12341                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12342                 R_SetupShader_Generic_NoTexture(false, false);
12343                 GL_DepthTest(false);
12344                 GL_DepthMask(false);
12345                 GL_DepthRange(0, 1);
12346                 GL_BlendFunc(GL_ONE, GL_ONE);
12347                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12348                 {
12349                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12350                                 continue;
12351                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12352                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12353                         {
12354                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12355                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12356                                 if (!rsurface.texture->currentlayers->depthmask)
12357                                         GL_Color(c, 0, 0, 1.0f);
12358                                 else if (ent == r_refdef.scene.worldentity)
12359                                         GL_Color(c, c, c, 1.0f);
12360                                 else
12361                                         GL_Color(0, c, 0, 1.0f);
12362                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12363                                 RSurf_DrawBatch();
12364                         }
12365                 }
12366                 rsurface.texture = NULL;
12367         }
12368
12369         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12370
12371 //      R_Mesh_ResetTextureState();
12372         R_SetupShader_Generic_NoTexture(false, false);
12373         GL_DepthRange(0, 1);
12374         GL_DepthTest(!r_showdisabledepthtest.integer);
12375         GL_DepthMask(false);
12376         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12377
12378         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12379         {
12380                 int triangleindex;
12381                 int bihleafindex;
12382                 qboolean cullbox = false;
12383                 const q3mbrush_t *brush;
12384                 const bih_t *bih = &model->collision_bih;
12385                 const bih_leaf_t *bihleaf;
12386                 float vertex3f[3][3];
12387                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12388                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12389                 {
12390                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12391                                 continue;
12392                         switch (bihleaf->type)
12393                         {
12394                         case BIH_BRUSH:
12395                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12396                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12397                                 {
12398                                         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);
12399                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12400                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12401                                 }
12402                                 break;
12403                         case BIH_COLLISIONTRIANGLE:
12404                                 triangleindex = bihleaf->itemindex;
12405                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12406                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12407                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12408                                 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);
12409                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12410                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12411                                 break;
12412                         case BIH_RENDERTRIANGLE:
12413                                 triangleindex = bihleaf->itemindex;
12414                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12415                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12416                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12417                                 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);
12418                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12419                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12420                                 break;
12421                         }
12422                 }
12423         }
12424
12425         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12426
12427 #ifndef USE_GLES2
12428         if (r_showtris.integer && qglPolygonMode)
12429         {
12430                 if (r_showdisabledepthtest.integer)
12431                 {
12432                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12433                         GL_DepthMask(false);
12434                 }
12435                 else
12436                 {
12437                         GL_BlendFunc(GL_ONE, GL_ZERO);
12438                         GL_DepthMask(true);
12439                 }
12440                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12441                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12442                 {
12443                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12444                                 continue;
12445                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12446                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12447                         {
12448                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12449                                 if (!rsurface.texture->currentlayers->depthmask)
12450                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12451                                 else if (ent == r_refdef.scene.worldentity)
12452                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12453                                 else
12454                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12455                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12456                                 RSurf_DrawBatch();
12457                         }
12458                 }
12459                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12460                 rsurface.texture = NULL;
12461         }
12462
12463         if (r_shownormals.value != 0 && qglBegin)
12464         {
12465                 int l, k;
12466                 vec3_t v;
12467                 if (r_showdisabledepthtest.integer)
12468                 {
12469                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12470                         GL_DepthMask(false);
12471                 }
12472                 else
12473                 {
12474                         GL_BlendFunc(GL_ONE, GL_ZERO);
12475                         GL_DepthMask(true);
12476                 }
12477                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12478                 {
12479                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12480                                 continue;
12481                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12482                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12483                         {
12484                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12485                                 qglBegin(GL_LINES);
12486                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12487                                 {
12488                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12489                                         {
12490                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12491                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12492                                                 qglVertex3f(v[0], v[1], v[2]);
12493                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12494                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12495                                                 qglVertex3f(v[0], v[1], v[2]);
12496                                         }
12497                                 }
12498                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12499                                 {
12500                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12501                                         {
12502                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12503                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12504                                                 qglVertex3f(v[0], v[1], v[2]);
12505                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12506                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12507                                                 qglVertex3f(v[0], v[1], v[2]);
12508                                         }
12509                                 }
12510                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12511                                 {
12512                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12513                                         {
12514                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12515                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12516                                                 qglVertex3f(v[0], v[1], v[2]);
12517                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12518                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12519                                                 qglVertex3f(v[0], v[1], v[2]);
12520                                         }
12521                                 }
12522                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12523                                 {
12524                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12525                                         {
12526                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12527                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12528                                                 qglVertex3f(v[0], v[1], v[2]);
12529                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12530                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12531                                                 qglVertex3f(v[0], v[1], v[2]);
12532                                         }
12533                                 }
12534                                 qglEnd();
12535                                 CHECKGLERROR
12536                         }
12537                 }
12538                 rsurface.texture = NULL;
12539         }
12540 #endif
12541 }
12542
12543 int r_maxsurfacelist = 0;
12544 const msurface_t **r_surfacelist = NULL;
12545 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12546 {
12547         int i, j, endj, flagsmask;
12548         dp_model_t *model = r_refdef.scene.worldmodel;
12549         msurface_t *surfaces;
12550         unsigned char *update;
12551         int numsurfacelist = 0;
12552         if (model == NULL)
12553                 return;
12554
12555         if (r_maxsurfacelist < model->num_surfaces)
12556         {
12557                 r_maxsurfacelist = model->num_surfaces;
12558                 if (r_surfacelist)
12559                         Mem_Free((msurface_t**)r_surfacelist);
12560                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12561         }
12562
12563         RSurf_ActiveWorldEntity();
12564
12565         surfaces = model->data_surfaces;
12566         update = model->brushq1.lightmapupdateflags;
12567
12568         // update light styles on this submodel
12569         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12570         {
12571                 model_brush_lightstyleinfo_t *style;
12572                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12573                 {
12574                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12575                         {
12576                                 int *list = style->surfacelist;
12577                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12578                                 for (j = 0;j < style->numsurfaces;j++)
12579                                         update[list[j]] = true;
12580                         }
12581                 }
12582         }
12583
12584         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12585
12586         if (debug)
12587         {
12588                 R_DrawDebugModel();
12589                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12590                 return;
12591         }
12592
12593         rsurface.lightmaptexture = NULL;
12594         rsurface.deluxemaptexture = NULL;
12595         rsurface.uselightmaptexture = false;
12596         rsurface.texture = NULL;
12597         rsurface.rtlight = NULL;
12598         numsurfacelist = 0;
12599         // add visible surfaces to draw list
12600         for (i = 0;i < model->nummodelsurfaces;i++)
12601         {
12602                 j = model->sortedmodelsurfaces[i];
12603                 if (r_refdef.viewcache.world_surfacevisible[j])
12604                         r_surfacelist[numsurfacelist++] = surfaces + j;
12605         }
12606         // update lightmaps if needed
12607         if (model->brushq1.firstrender)
12608         {
12609                 model->brushq1.firstrender = false;
12610                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12611                         if (update[j])
12612                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12613         }
12614         else if (update)
12615         {
12616                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12617                         if (r_refdef.viewcache.world_surfacevisible[j])
12618                                 if (update[j])
12619                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12620         }
12621         // don't do anything if there were no surfaces
12622         if (!numsurfacelist)
12623         {
12624                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12625                 return;
12626         }
12627         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12628
12629         // add to stats if desired
12630         if (r_speeds.integer && !skysurfaces && !depthonly)
12631         {
12632                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12633                 for (j = 0;j < numsurfacelist;j++)
12634                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12635         }
12636
12637         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12638 }
12639
12640 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12641 {
12642         int i, j, endj, flagsmask;
12643         dp_model_t *model = ent->model;
12644         msurface_t *surfaces;
12645         unsigned char *update;
12646         int numsurfacelist = 0;
12647         if (model == NULL)
12648                 return;
12649
12650         if (r_maxsurfacelist < model->num_surfaces)
12651         {
12652                 r_maxsurfacelist = model->num_surfaces;
12653                 if (r_surfacelist)
12654                         Mem_Free((msurface_t **)r_surfacelist);
12655                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12656         }
12657
12658         // if the model is static it doesn't matter what value we give for
12659         // wantnormals and wanttangents, so this logic uses only rules applicable
12660         // to a model, knowing that they are meaningless otherwise
12661         if (ent == r_refdef.scene.worldentity)
12662                 RSurf_ActiveWorldEntity();
12663         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12664                 RSurf_ActiveModelEntity(ent, false, false, false);
12665         else if (prepass)
12666                 RSurf_ActiveModelEntity(ent, true, true, true);
12667         else if (depthonly)
12668         {
12669                 switch (vid.renderpath)
12670                 {
12671                 case RENDERPATH_GL20:
12672                 case RENDERPATH_D3D9:
12673                 case RENDERPATH_D3D10:
12674                 case RENDERPATH_D3D11:
12675                 case RENDERPATH_SOFT:
12676                 case RENDERPATH_GLES2:
12677                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12678                         break;
12679                 case RENDERPATH_GL11:
12680                 case RENDERPATH_GL13:
12681                 case RENDERPATH_GLES1:
12682                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12683                         break;
12684                 }
12685         }
12686         else
12687         {
12688                 switch (vid.renderpath)
12689                 {
12690                 case RENDERPATH_GL20:
12691                 case RENDERPATH_D3D9:
12692                 case RENDERPATH_D3D10:
12693                 case RENDERPATH_D3D11:
12694                 case RENDERPATH_SOFT:
12695                 case RENDERPATH_GLES2:
12696                         RSurf_ActiveModelEntity(ent, true, true, false);
12697                         break;
12698                 case RENDERPATH_GL11:
12699                 case RENDERPATH_GL13:
12700                 case RENDERPATH_GLES1:
12701                         RSurf_ActiveModelEntity(ent, true, false, false);
12702                         break;
12703                 }
12704         }
12705
12706         surfaces = model->data_surfaces;
12707         update = model->brushq1.lightmapupdateflags;
12708
12709         // update light styles
12710         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12711         {
12712                 model_brush_lightstyleinfo_t *style;
12713                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12714                 {
12715                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12716                         {
12717                                 int *list = style->surfacelist;
12718                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12719                                 for (j = 0;j < style->numsurfaces;j++)
12720                                         update[list[j]] = true;
12721                         }
12722                 }
12723         }
12724
12725         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12726
12727         if (debug)
12728         {
12729                 R_DrawDebugModel();
12730                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12731                 return;
12732         }
12733
12734         rsurface.lightmaptexture = NULL;
12735         rsurface.deluxemaptexture = NULL;
12736         rsurface.uselightmaptexture = false;
12737         rsurface.texture = NULL;
12738         rsurface.rtlight = NULL;
12739         numsurfacelist = 0;
12740         // add visible surfaces to draw list
12741         for (i = 0;i < model->nummodelsurfaces;i++)
12742                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12743         // don't do anything if there were no surfaces
12744         if (!numsurfacelist)
12745         {
12746                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12747                 return;
12748         }
12749         // update lightmaps if needed
12750         if (update)
12751         {
12752                 int updated = 0;
12753                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12754                 {
12755                         if (update[j])
12756                         {
12757                                 updated++;
12758                                 R_BuildLightMap(ent, surfaces + j);
12759                         }
12760                 }
12761         }
12762
12763         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12764
12765         // add to stats if desired
12766         if (r_speeds.integer && !skysurfaces && !depthonly)
12767         {
12768                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12769                 for (j = 0;j < numsurfacelist;j++)
12770                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12771         }
12772
12773         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12774 }
12775
12776 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12777 {
12778         static texture_t texture;
12779         static msurface_t surface;
12780         const msurface_t *surfacelist = &surface;
12781
12782         // fake enough texture and surface state to render this geometry
12783
12784         texture.update_lastrenderframe = -1; // regenerate this texture
12785         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12786         texture.basealpha = 1.0f;
12787         texture.currentskinframe = skinframe;
12788         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12789         texture.offsetmapping = OFFSETMAPPING_OFF;
12790         texture.offsetscale = 1;
12791         texture.specularscalemod = 1;
12792         texture.specularpowermod = 1;
12793         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12794         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12795         // JUST GREP FOR "specularscalemod = 1".
12796
12797         surface.texture = &texture;
12798         surface.num_triangles = numtriangles;
12799         surface.num_firsttriangle = firsttriangle;
12800         surface.num_vertices = numvertices;
12801         surface.num_firstvertex = firstvertex;
12802
12803         // now render it
12804         rsurface.texture = R_GetCurrentTexture(surface.texture);
12805         rsurface.lightmaptexture = NULL;
12806         rsurface.deluxemaptexture = NULL;
12807         rsurface.uselightmaptexture = false;
12808         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12809 }
12810
12811 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)
12812 {
12813         static msurface_t surface;
12814         const msurface_t *surfacelist = &surface;
12815
12816         // fake enough texture and surface state to render this geometry
12817         surface.texture = texture;
12818         surface.num_triangles = numtriangles;
12819         surface.num_firsttriangle = firsttriangle;
12820         surface.num_vertices = numvertices;
12821         surface.num_firstvertex = firstvertex;
12822
12823         // now render it
12824         rsurface.texture = R_GetCurrentTexture(surface.texture);
12825         rsurface.lightmaptexture = NULL;
12826         rsurface.deluxemaptexture = NULL;
12827         rsurface.uselightmaptexture = false;
12828         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12829 }