]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added cl_bob_limit cvar which limits the maximum rage of view bobbing in a smooth...
[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_shadowmap_texturescale[2];
2140 extern float r_shadow_shadowmap_parameters[4];
2141 extern qboolean r_shadow_shadowmapvsdct;
2142 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2143 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2144 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2145 extern matrix4x4_t r_shadow_shadowmapmatrix;
2146 extern int r_shadow_prepass_width;
2147 extern int r_shadow_prepass_height;
2148 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2149 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2150 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2151 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2152
2153 #define BLENDFUNC_ALLOWS_COLORMOD      1
2154 #define BLENDFUNC_ALLOWS_FOG           2
2155 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2156 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2157 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2158 static int R_BlendFuncFlags(int src, int dst)
2159 {
2160         int r = 0;
2161
2162         // a blendfunc allows colormod if:
2163         // a) it can never keep the destination pixel invariant, or
2164         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2165         // this is to prevent unintended side effects from colormod
2166
2167         // a blendfunc allows fog if:
2168         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2169         // this is to prevent unintended side effects from fog
2170
2171         // these checks are the output of fogeval.pl
2172
2173         r |= BLENDFUNC_ALLOWS_COLORMOD;
2174         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2176         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2182         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2183         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2184         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2185         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2187         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2188         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2189         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195
2196         return r;
2197 }
2198
2199 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)
2200 {
2201         // select a permutation of the lighting shader appropriate to this
2202         // combination of texture, entity, light source, and fogging, only use the
2203         // minimum features necessary to avoid wasting rendering time in the
2204         // fragment shader on features that are not being used
2205         unsigned int permutation = 0;
2206         unsigned int mode = 0;
2207         int blendfuncflags;
2208         static float dummy_colormod[3] = {1, 1, 1};
2209         float *colormod = rsurface.colormod;
2210         float m16f[16];
2211         matrix4x4_t tempmatrix;
2212         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2213         if (r_trippy.integer && !notrippy)
2214                 permutation |= SHADERPERMUTATION_TRIPPY;
2215         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2216                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2217         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2218                 permutation |= SHADERPERMUTATION_OCCLUDE;
2219         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2220                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2221         if (rsurfacepass == RSURFPASS_BACKGROUND)
2222         {
2223                 // distorted background
2224                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2225                 {
2226                         mode = SHADERMODE_WATER;
2227                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2230                         {
2231                                 // this is the right thing to do for wateralpha
2232                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2233                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2234                         }
2235                         else
2236                         {
2237                                 // this is the right thing to do for entity alpha
2238                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                         }
2241                 }
2242                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2243                 {
2244                         mode = SHADERMODE_REFRACTION;
2245                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2246                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2247                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2248                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249                 }
2250                 else
2251                 {
2252                         mode = SHADERMODE_GENERIC;
2253                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2254                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                 }
2257                 if (vid.allowalphatocoverage)
2258                         GL_AlphaToCoverage(false);
2259         }
2260         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2261         {
2262                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2263                 {
2264                         switch(rsurface.texture->offsetmapping)
2265                         {
2266                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2267                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2268                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269                         case OFFSETMAPPING_OFF: break;
2270                         }
2271                 }
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2273                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2274                 // normalmap (deferred prepass), may use alpha test on diffuse
2275                 mode = SHADERMODE_DEFERREDGEOMETRY;
2276                 GL_BlendFunc(GL_ONE, GL_ZERO);
2277                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2278                 if (vid.allowalphatocoverage)
2279                         GL_AlphaToCoverage(false);
2280         }
2281         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2282         {
2283                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2284                 {
2285                         switch(rsurface.texture->offsetmapping)
2286                         {
2287                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2288                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_OFF: break;
2291                         }
2292                 }
2293                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2294                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2295                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2296                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2297                 // light source
2298                 mode = SHADERMODE_LIGHTSOURCE;
2299                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2300                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2301                 if (diffusescale > 0)
2302                         permutation |= SHADERPERMUTATION_DIFFUSE;
2303                 if (specularscale > 0)
2304                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2305                 if (r_refdef.fogenabled)
2306                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307                 if (rsurface.texture->colormapping)
2308                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2309                 if (r_shadow_usingshadowmap2d)
2310                 {
2311                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312                         if(r_shadow_shadowmapvsdct)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2314
2315                         if (r_shadow_shadowmap2ddepthbuffer)
2316                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2317                 }
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2321                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2322                 if (vid.allowalphatocoverage)
2323                         GL_AlphaToCoverage(false);
2324         }
2325         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2326         {
2327                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2328                 {
2329                         switch(rsurface.texture->offsetmapping)
2330                         {
2331                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2332                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2333                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334                         case OFFSETMAPPING_OFF: break;
2335                         }
2336                 }
2337                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2338                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2340                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2341                 // unshaded geometry (fullbright or ambient model lighting)
2342                 mode = SHADERMODE_FLATCOLOR;
2343                 ambientscale = diffusescale = specularscale = 0;
2344                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2345                         permutation |= SHADERPERMUTATION_GLOW;
2346                 if (r_refdef.fogenabled)
2347                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2348                 if (rsurface.texture->colormapping)
2349                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2350                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2351                 {
2352                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2353                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2354
2355                         if (r_shadow_shadowmap2ddepthbuffer)
2356                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2357                 }
2358                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2359                         permutation |= SHADERPERMUTATION_REFLECTION;
2360                 if (rsurface.texture->reflectmasktexture)
2361                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2362                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364                 // when using alphatocoverage, we don't need alphakill
2365                 if (vid.allowalphatocoverage)
2366                 {
2367                         if (r_transparent_alphatocoverage.integer)
2368                         {
2369                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2370                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2371                         }
2372                         else
2373                                 GL_AlphaToCoverage(false);
2374                 }
2375         }
2376         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2377         {
2378                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2379                 {
2380                         switch(rsurface.texture->offsetmapping)
2381                         {
2382                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2383                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385                         case OFFSETMAPPING_OFF: break;
2386                         }
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2389                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2391                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2392                 // directional model lighting
2393                 mode = SHADERMODE_LIGHTDIRECTION;
2394                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2395                         permutation |= SHADERPERMUTATION_GLOW;
2396                 permutation |= SHADERPERMUTATION_DIFFUSE;
2397                 if (specularscale > 0)
2398                         permutation |= SHADERPERMUTATION_SPECULAR;
2399                 if (r_refdef.fogenabled)
2400                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2401                 if (rsurface.texture->colormapping)
2402                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2403                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2404                 {
2405                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2406                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2407
2408                         if (r_shadow_shadowmap2ddepthbuffer)
2409                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2410                 }
2411                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2412                         permutation |= SHADERPERMUTATION_REFLECTION;
2413                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2414                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2415                 if (rsurface.texture->reflectmasktexture)
2416                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2417                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2418                 {
2419                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2420                         if (r_shadow_bouncegrid_state.directional)
2421                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2422                 }
2423                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2424                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 // when using alphatocoverage, we don't need alphakill
2426                 if (vid.allowalphatocoverage)
2427                 {
2428                         if (r_transparent_alphatocoverage.integer)
2429                         {
2430                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2431                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2432                         }
2433                         else
2434                                 GL_AlphaToCoverage(false);
2435                 }
2436         }
2437         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2438         {
2439                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2440                 {
2441                         switch(rsurface.texture->offsetmapping)
2442                         {
2443                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2444                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2445                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446                         case OFFSETMAPPING_OFF: break;
2447                         }
2448                 }
2449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2450                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2452                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2453                 // ambient model lighting
2454                 mode = SHADERMODE_LIGHTDIRECTION;
2455                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2456                         permutation |= SHADERPERMUTATION_GLOW;
2457                 if (r_refdef.fogenabled)
2458                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2459                 if (rsurface.texture->colormapping)
2460                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2461                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2462                 {
2463                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2464                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2465
2466                         if (r_shadow_shadowmap2ddepthbuffer)
2467                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2468                 }
2469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2470                         permutation |= SHADERPERMUTATION_REFLECTION;
2471                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2472                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2473                 if (rsurface.texture->reflectmasktexture)
2474                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2475                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2476                 {
2477                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2478                         if (r_shadow_bouncegrid_state.directional)
2479                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2480                 }
2481                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2482                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 // when using alphatocoverage, we don't need alphakill
2484                 if (vid.allowalphatocoverage)
2485                 {
2486                         if (r_transparent_alphatocoverage.integer)
2487                         {
2488                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2489                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2490                         }
2491                         else
2492                                 GL_AlphaToCoverage(false);
2493                 }
2494         }
2495         else
2496         {
2497                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2498                 {
2499                         switch(rsurface.texture->offsetmapping)
2500                         {
2501                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2502                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2503                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504                         case OFFSETMAPPING_OFF: break;
2505                         }
2506                 }
2507                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2508                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2510                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2511                 // lightmapped wall
2512                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2513                         permutation |= SHADERPERMUTATION_GLOW;
2514                 if (r_refdef.fogenabled)
2515                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2516                 if (rsurface.texture->colormapping)
2517                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2518                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2519                 {
2520                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2521                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2522
2523                         if (r_shadow_shadowmap2ddepthbuffer)
2524                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2525                 }
2526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2527                         permutation |= SHADERPERMUTATION_REFLECTION;
2528                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2529                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2530                 if (rsurface.texture->reflectmasktexture)
2531                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2532                 if (FAKELIGHT_ENABLED)
2533                 {
2534                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2535                         mode = SHADERMODE_FAKELIGHT;
2536                         permutation |= SHADERPERMUTATION_DIFFUSE;
2537                         if (specularscale > 0)
2538                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2539                 }
2540                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2541                 {
2542                         // deluxemapping (light direction texture)
2543                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2544                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2545                         else
2546                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2547                         permutation |= SHADERPERMUTATION_DIFFUSE;
2548                         if (specularscale > 0)
2549                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2550                 }
2551                 else if (r_glsl_deluxemapping.integer >= 2)
2552                 {
2553                         // fake deluxemapping (uniform light direction in tangentspace)
2554                         if (rsurface.uselightmaptexture)
2555                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2556                         else
2557                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2558                         permutation |= SHADERPERMUTATION_DIFFUSE;
2559                         if (specularscale > 0)
2560                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2561                 }
2562                 else if (rsurface.uselightmaptexture)
2563                 {
2564                         // ordinary lightmapping (q1bsp, q3bsp)
2565                         mode = SHADERMODE_LIGHTMAP;
2566                 }
2567                 else
2568                 {
2569                         // ordinary vertex coloring (q3bsp)
2570                         mode = SHADERMODE_VERTEXCOLOR;
2571                 }
2572                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2573                 {
2574                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2575                         if (r_shadow_bouncegrid_state.directional)
2576                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2577                 }
2578                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2579                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580                 // when using alphatocoverage, we don't need alphakill
2581                 if (vid.allowalphatocoverage)
2582                 {
2583                         if (r_transparent_alphatocoverage.integer)
2584                         {
2585                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2586                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2587                         }
2588                         else
2589                                 GL_AlphaToCoverage(false);
2590                 }
2591         }
2592         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2593                 colormod = dummy_colormod;
2594         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2595                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2596         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2597                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2598         switch(vid.renderpath)
2599         {
2600         case RENDERPATH_D3D9:
2601 #ifdef SUPPORTD3D
2602                 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);
2603                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2604                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2605                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2606                 if (mode == SHADERMODE_LIGHTSOURCE)
2607                 {
2608                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2609                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610                 }
2611                 else
2612                 {
2613                         if (mode == SHADERMODE_LIGHTDIRECTION)
2614                         {
2615                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2616                         }
2617                 }
2618                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2619                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2620                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2621                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2622                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2623
2624                 if (mode == SHADERMODE_LIGHTSOURCE)
2625                 {
2626                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2627                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2628                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2631
2632                         // additive passes are only darkened by fog, not tinted
2633                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2634                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2635                 }
2636                 else
2637                 {
2638                         if (mode == SHADERMODE_FLATCOLOR)
2639                         {
2640                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2641                         }
2642                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2643                         {
2644                                 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]);
2645                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2646                                 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);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2649                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2651                         }
2652                         else
2653                         {
2654                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2656                                 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);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2659                         }
2660                         // additive passes are only darkened by fog, not tinted
2661                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2662                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2663                         else
2664                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2665                         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);
2666                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2667                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2668                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2669                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2671                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2672                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2673                         if (mode == SHADERMODE_WATER)
2674                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2675                 }
2676                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2677                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2678                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2679                 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));
2680                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2681                 if (rsurface.texture->pantstexture)
2682                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2683                 else
2684                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2685                 if (rsurface.texture->shirttexture)
2686                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2687                 else
2688                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2689                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2690                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2691                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2692                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2693                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2694                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2695                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2696                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2698                         );
2699                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2700                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2701                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2702                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2703
2704                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2705                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2706                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2707                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2708                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2709                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2710                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2711                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2712                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2713                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2714                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2715                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2717                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2718                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2721                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2722                 {
2723                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2726                 }
2727                 else
2728                 {
2729                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2730                 }
2731 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2732                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2733                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2734                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2735                 {
2736                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2737                         if (rsurface.rtlight)
2738                         {
2739                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2740                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2741                         }
2742                 }
2743 #endif
2744                 break;
2745         case RENDERPATH_D3D10:
2746                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2747                 break;
2748         case RENDERPATH_D3D11:
2749                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2750                 break;
2751         case RENDERPATH_GL20:
2752         case RENDERPATH_GLES2:
2753                 if (!vid.useinterleavedarrays)
2754                 {
2755                         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);
2756                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2757                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2758                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2759                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2760                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2761                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2762                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2763                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2764                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2765                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2766                 }
2767                 else
2768                 {
2769                         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);
2770                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2771                 }
2772                 // this has to be after RSurf_PrepareVerticesForBatch
2773                 if (rsurface.batchskeletaltransform3x4buffer)
2774                         permutation |= SHADERPERMUTATION_SKELETAL;
2775                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2776 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2777                 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);
2778 #endif
2779                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2780                 if (mode == SHADERMODE_LIGHTSOURCE)
2781                 {
2782                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2783                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2784                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2785                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2786                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2787                         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);
2788         
2789                         // additive passes are only darkened by fog, not tinted
2790                         if (r_glsl_permutation->loc_FogColor >= 0)
2791                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2792                         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);
2793                 }
2794                 else
2795                 {
2796                         if (mode == SHADERMODE_FLATCOLOR)
2797                         {
2798                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2799                         }
2800                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2801                         {
2802                                 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]);
2803                                 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]);
2804                                 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);
2805                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2806                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2807                                 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]);
2808                                 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]);
2809                         }
2810                         else
2811                         {
2812                                 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]);
2813                                 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]);
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] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2816                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2817                         }
2818                         // additive passes are only darkened by fog, not tinted
2819                         if (r_glsl_permutation->loc_FogColor >= 0)
2820                         {
2821                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2822                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2823                                 else
2824                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2825                         }
2826                         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);
2827                         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]);
2828                         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]);
2829                         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]);
2830                         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]);
2831                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2832                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2833                         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);
2834                         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]);
2835                 }
2836                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2837                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2838                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2839                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2840                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2841
2842                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2843                 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));
2844                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2845                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2846                 {
2847                         if (rsurface.texture->pantstexture)
2848                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2849                         else
2850                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2851                 }
2852                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2853                 {
2854                         if (rsurface.texture->shirttexture)
2855                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2856                         else
2857                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2858                 }
2859                 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]);
2860                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2861                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2862                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2863                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2864                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2865                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2866                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2868                         );
2869                 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);
2870                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2871                 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]);
2872                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2873                 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);}
2874                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2875
2876                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2877                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2878                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2879                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2880                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2881                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2882                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2883                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2884                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2885                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2886                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2887                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2888                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2889                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2890                 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);
2891                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2892                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2893                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2894                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2895                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2896                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2897                 {
2898                         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);
2899                         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);
2900                         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);
2901                 }
2902                 else
2903                 {
2904                         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);
2905                 }
2906                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2907                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2908                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2909                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2910                 {
2911                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2912                         if (rsurface.rtlight)
2913                         {
2914                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2915                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2916                         }
2917                 }
2918                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2919                 CHECKGLERROR
2920                 break;
2921         case RENDERPATH_GL11:
2922         case RENDERPATH_GL13:
2923         case RENDERPATH_GLES1:
2924                 break;
2925         case RENDERPATH_SOFT:
2926                 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);
2927                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2928                 R_SetupShader_SetPermutationSoft(mode, permutation);
2929                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2930                 if (mode == SHADERMODE_LIGHTSOURCE)
2931                 {
2932                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2933                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2934                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2935                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2936                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2938         
2939                         // additive passes are only darkened by fog, not tinted
2940                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2941                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2942                 }
2943                 else
2944                 {
2945                         if (mode == SHADERMODE_FLATCOLOR)
2946                         {
2947                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2948                         }
2949                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2950                         {
2951                                 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]);
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2953                                 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);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2956                                 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]);
2957                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2958                         }
2959                         else
2960                         {
2961                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2962                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2963                                 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);
2964                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2965                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2966                         }
2967                         // additive passes are only darkened by fog, not tinted
2968                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2969                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2970                         else
2971                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2972                         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);
2973                         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]);
2974                         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]);
2975                         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]);
2976                         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]);
2977                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2978                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2979                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2980                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2981                 }
2982                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2983                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2984                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2985                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2986                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2987
2988                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2989                 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));
2990                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2991                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2992                 {
2993                         if (rsurface.texture->pantstexture)
2994                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2995                         else
2996                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2997                 }
2998                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2999                 {
3000                         if (rsurface.texture->shirttexture)
3001                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3002                         else
3003                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3004                 }
3005                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3006                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3007                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3008                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3009                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3010                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3011                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3012                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3014                         );
3015                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3016                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3017                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3018                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3019
3020                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3021                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3022                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3023                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3024                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3025                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3026                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3027                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3028                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3029                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3030                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3031                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3032                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3033                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3034                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3035                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3036                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3037                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3038                 {
3039                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3040                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3041                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3042                 }
3043                 else
3044                 {
3045                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3046                 }
3047 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3048                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3049                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3050                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3051                 {
3052                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3053                         if (rsurface.rtlight)
3054                         {
3055                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3056                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3057                         }
3058                 }
3059                 break;
3060         }
3061 }
3062
3063 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3064 {
3065         // select a permutation of the lighting shader appropriate to this
3066         // combination of texture, entity, light source, and fogging, only use the
3067         // minimum features necessary to avoid wasting rendering time in the
3068         // fragment shader on features that are not being used
3069         unsigned int permutation = 0;
3070         unsigned int mode = 0;
3071         const float *lightcolorbase = rtlight->currentcolor;
3072         float ambientscale = rtlight->ambientscale;
3073         float diffusescale = rtlight->diffusescale;
3074         float specularscale = rtlight->specularscale;
3075         // this is the location of the light in view space
3076         vec3_t viewlightorigin;
3077         // this transforms from view space (camera) to light space (cubemap)
3078         matrix4x4_t viewtolight;
3079         matrix4x4_t lighttoview;
3080         float viewtolight16f[16];
3081         // light source
3082         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3083         if (rtlight->currentcubemap != r_texture_whitecube)
3084                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3085         if (diffusescale > 0)
3086                 permutation |= SHADERPERMUTATION_DIFFUSE;
3087         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3088                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3089         if (r_shadow_usingshadowmap2d)
3090         {
3091                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3092                 if (r_shadow_shadowmapvsdct)
3093                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3094
3095                 if (r_shadow_shadowmap2ddepthbuffer)
3096                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3097         }
3098         if (vid.allowalphatocoverage)
3099                 GL_AlphaToCoverage(false);
3100         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3101         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3102         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3103         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3104         switch(vid.renderpath)
3105         {
3106         case RENDERPATH_D3D9:
3107 #ifdef SUPPORTD3D
3108                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3109                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3110                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3111                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3112                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3113                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3114                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3115                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3116                 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);
3117                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3118                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3119
3120                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3121                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3122                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3123                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3124                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3125 #endif
3126                 break;
3127         case RENDERPATH_D3D10:
3128                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3129                 break;
3130         case RENDERPATH_D3D11:
3131                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3132                 break;
3133         case RENDERPATH_GL20:
3134         case RENDERPATH_GLES2:
3135                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3136                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3137                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3138                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3139                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3140                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3141                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3142                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3143                 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);
3144                 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]);
3145                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3146
3147                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3148                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3149                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3150                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3151                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3152                 break;
3153         case RENDERPATH_GL11:
3154         case RENDERPATH_GL13:
3155         case RENDERPATH_GLES1:
3156                 break;
3157         case RENDERPATH_SOFT:
3158                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3159                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3160                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3161                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3162                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3163                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3164                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3165                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3166                 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);
3167                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3168                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3169
3170                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3171                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3172                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3173                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3174                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3175                 break;
3176         }
3177 }
3178
3179 #define SKINFRAME_HASH 1024
3180
3181 typedef struct
3182 {
3183         unsigned int loadsequence; // incremented each level change
3184         memexpandablearray_t array;
3185         skinframe_t *hash[SKINFRAME_HASH];
3186 }
3187 r_skinframe_t;
3188 r_skinframe_t r_skinframe;
3189
3190 void R_SkinFrame_PrepareForPurge(void)
3191 {
3192         r_skinframe.loadsequence++;
3193         // wrap it without hitting zero
3194         if (r_skinframe.loadsequence >= 200)
3195                 r_skinframe.loadsequence = 1;
3196 }
3197
3198 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3199 {
3200         if (!skinframe)
3201                 return;
3202         // mark the skinframe as used for the purging code
3203         skinframe->loadsequence = r_skinframe.loadsequence;
3204 }
3205
3206 void R_SkinFrame_Purge(void)
3207 {
3208         int i;
3209         skinframe_t *s;
3210         for (i = 0;i < SKINFRAME_HASH;i++)
3211         {
3212                 for (s = r_skinframe.hash[i];s;s = s->next)
3213                 {
3214                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3215                         {
3216                                 if (s->merged == s->base)
3217                                         s->merged = NULL;
3218                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3219                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3220                                 R_PurgeTexture(s->merged);s->merged = NULL;
3221                                 R_PurgeTexture(s->base  );s->base   = NULL;
3222                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3223                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3224                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3225                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3226                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3227                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3228                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3229                                 s->loadsequence = 0;
3230                         }
3231                 }
3232         }
3233 }
3234
3235 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3236         skinframe_t *item;
3237         char basename[MAX_QPATH];
3238
3239         Image_StripImageExtension(name, basename, sizeof(basename));
3240
3241         if( last == NULL ) {
3242                 int hashindex;
3243                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3244                 item = r_skinframe.hash[hashindex];
3245         } else {
3246                 item = last->next;
3247         }
3248
3249         // linearly search through the hash bucket
3250         for( ; item ; item = item->next ) {
3251                 if( !strcmp( item->basename, basename ) ) {
3252                         return item;
3253                 }
3254         }
3255         return NULL;
3256 }
3257
3258 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3259 {
3260         skinframe_t *item;
3261         int hashindex;
3262         char basename[MAX_QPATH];
3263
3264         Image_StripImageExtension(name, basename, sizeof(basename));
3265
3266         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3267         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3268                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3269                         break;
3270
3271         if (!item) {
3272                 rtexture_t *dyntexture;
3273                 // check whether its a dynamic texture
3274                 dyntexture = CL_GetDynTexture( basename );
3275                 if (!add && !dyntexture)
3276                         return NULL;
3277                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3278                 memset(item, 0, sizeof(*item));
3279                 strlcpy(item->basename, basename, sizeof(item->basename));
3280                 item->base = dyntexture; // either NULL or dyntexture handle
3281                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3282                 item->comparewidth = comparewidth;
3283                 item->compareheight = compareheight;
3284                 item->comparecrc = comparecrc;
3285                 item->next = r_skinframe.hash[hashindex];
3286                 r_skinframe.hash[hashindex] = item;
3287         }
3288         else if (textureflags & TEXF_FORCE_RELOAD)
3289         {
3290                 rtexture_t *dyntexture;
3291                 // check whether its a dynamic texture
3292                 dyntexture = CL_GetDynTexture( basename );
3293                 if (!add && !dyntexture)
3294                         return NULL;
3295                 if (item->merged == item->base)
3296                         item->merged = NULL;
3297                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3298                 R_PurgeTexture(item->stain );item->stain  = NULL;
3299                 R_PurgeTexture(item->merged);item->merged = NULL;
3300                 R_PurgeTexture(item->base  );item->base   = NULL;
3301                 R_PurgeTexture(item->pants );item->pants  = NULL;
3302                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3303                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3304                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3305                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3306                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3307         R_PurgeTexture(item->reflect);item->reflect = NULL;
3308                 item->loadsequence = 0;
3309         }
3310         else if( item->base == NULL )
3311         {
3312                 rtexture_t *dyntexture;
3313                 // check whether its a dynamic texture
3314                 // 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]
3315                 dyntexture = CL_GetDynTexture( basename );
3316                 item->base = dyntexture; // either NULL or dyntexture handle
3317         }
3318
3319         R_SkinFrame_MarkUsed(item);
3320         return item;
3321 }
3322
3323 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3324         { \
3325                 unsigned long long avgcolor[5], wsum; \
3326                 int pix, comp, w; \
3327                 avgcolor[0] = 0; \
3328                 avgcolor[1] = 0; \
3329                 avgcolor[2] = 0; \
3330                 avgcolor[3] = 0; \
3331                 avgcolor[4] = 0; \
3332                 wsum = 0; \
3333                 for(pix = 0; pix < cnt; ++pix) \
3334                 { \
3335                         w = 0; \
3336                         for(comp = 0; comp < 3; ++comp) \
3337                                 w += getpixel; \
3338                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3339                         { \
3340                                 ++wsum; \
3341                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3342                                 w = getpixel; \
3343                                 for(comp = 0; comp < 3; ++comp) \
3344                                         avgcolor[comp] += getpixel * w; \
3345                                 avgcolor[3] += w; \
3346                         } \
3347                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3348                         avgcolor[4] += getpixel; \
3349                 } \
3350                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3351                         avgcolor[3] = 1; \
3352                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3353                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3354                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3355                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3356         }
3357
3358 extern cvar_t gl_picmip;
3359 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3360 {
3361         int j;
3362         unsigned char *pixels;
3363         unsigned char *bumppixels;
3364         unsigned char *basepixels = NULL;
3365         int basepixels_width = 0;
3366         int basepixels_height = 0;
3367         skinframe_t *skinframe;
3368         rtexture_t *ddsbase = NULL;
3369         qboolean ddshasalpha = false;
3370         float ddsavgcolor[4];
3371         char basename[MAX_QPATH];
3372         int miplevel = R_PicmipForFlags(textureflags);
3373         int savemiplevel = miplevel;
3374         int mymiplevel;
3375         char vabuf[1024];
3376
3377         if (cls.state == ca_dedicated)
3378                 return NULL;
3379
3380         // return an existing skinframe if already loaded
3381         // if loading of the first image fails, don't make a new skinframe as it
3382         // would cause all future lookups of this to be missing
3383         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3384         if (skinframe && skinframe->base)
3385                 return skinframe;
3386
3387         Image_StripImageExtension(name, basename, sizeof(basename));
3388
3389         // check for DDS texture file first
3390         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3391         {
3392                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3393                 if (basepixels == NULL)
3394                         return NULL;
3395         }
3396
3397         // FIXME handle miplevel
3398
3399         if (developer_loading.integer)
3400                 Con_Printf("loading skin \"%s\"\n", name);
3401
3402         // we've got some pixels to store, so really allocate this new texture now
3403         if (!skinframe)
3404                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3405         textureflags &= ~TEXF_FORCE_RELOAD;
3406         skinframe->stain = NULL;
3407         skinframe->merged = NULL;
3408         skinframe->base = NULL;
3409         skinframe->pants = NULL;
3410         skinframe->shirt = NULL;
3411         skinframe->nmap = NULL;
3412         skinframe->gloss = NULL;
3413         skinframe->glow = NULL;
3414         skinframe->fog = NULL;
3415         skinframe->reflect = NULL;
3416         skinframe->hasalpha = false;
3417         // we could store the q2animname here too
3418
3419         if (ddsbase)
3420         {
3421                 skinframe->base = ddsbase;
3422                 skinframe->hasalpha = ddshasalpha;
3423                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3424                 if (r_loadfog && skinframe->hasalpha)
3425                         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);
3426                 //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]);
3427         }
3428         else
3429         {
3430                 basepixels_width = image_width;
3431                 basepixels_height = image_height;
3432                 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);
3433                 if (textureflags & TEXF_ALPHA)
3434                 {
3435                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3436                         {
3437                                 if (basepixels[j] < 255)
3438                                 {
3439                                         skinframe->hasalpha = true;
3440                                         break;
3441                                 }
3442                         }
3443                         if (r_loadfog && skinframe->hasalpha)
3444                         {
3445                                 // has transparent pixels
3446                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3447                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3448                                 {
3449                                         pixels[j+0] = 255;
3450                                         pixels[j+1] = 255;
3451                                         pixels[j+2] = 255;
3452                                         pixels[j+3] = basepixels[j+3];
3453                                 }
3454                                 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);
3455                                 Mem_Free(pixels);
3456                         }
3457                 }
3458                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3459 #ifndef USE_GLES2
3460                 //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]);
3461                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3462                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3463                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3464                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3465 #endif
3466         }
3467
3468         if (r_loaddds)
3469         {
3470                 mymiplevel = savemiplevel;
3471                 if (r_loadnormalmap)
3472                         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);
3473                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3474                 if (r_loadgloss)
3475                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3476                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3479         }
3480
3481         // _norm is the name used by tenebrae and has been adopted as standard
3482         if (r_loadnormalmap && skinframe->nmap == NULL)
3483         {
3484                 mymiplevel = savemiplevel;
3485                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3486                 {
3487                         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);
3488                         Mem_Free(pixels);
3489                         pixels = NULL;
3490                 }
3491                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3492                 {
3493                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3494                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3495                         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);
3496                         Mem_Free(pixels);
3497                         Mem_Free(bumppixels);
3498                 }
3499                 else if (r_shadow_bumpscale_basetexture.value > 0)
3500                 {
3501                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3502                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3503                         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);
3504                         Mem_Free(pixels);
3505                 }
3506 #ifndef USE_GLES2
3507                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3508                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3509 #endif
3510         }
3511
3512         // _luma is supported only for tenebrae compatibility
3513         // _glow is the preferred name
3514         mymiplevel = savemiplevel;
3515         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))))
3516         {
3517                 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);
3518 #ifndef USE_GLES2
3519                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3520                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3521 #endif
3522                 Mem_Free(pixels);pixels = NULL;
3523         }
3524
3525         mymiplevel = savemiplevel;
3526         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3527         {
3528                 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);
3529 #ifndef USE_GLES2
3530                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3531                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3532 #endif
3533                 Mem_Free(pixels);
3534                 pixels = NULL;
3535         }
3536
3537         mymiplevel = savemiplevel;
3538         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3539         {
3540                 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);
3541 #ifndef USE_GLES2
3542                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3543                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3544 #endif
3545                 Mem_Free(pixels);
3546                 pixels = NULL;
3547         }
3548
3549         mymiplevel = savemiplevel;
3550         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3551         {
3552                 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);
3553 #ifndef USE_GLES2
3554                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3555                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3556 #endif
3557                 Mem_Free(pixels);
3558                 pixels = NULL;
3559         }
3560
3561         mymiplevel = savemiplevel;
3562         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3563         {
3564                 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);
3565 #ifndef USE_GLES2
3566                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3567                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3568 #endif
3569                 Mem_Free(pixels);
3570                 pixels = NULL;
3571         }
3572
3573         if (basepixels)
3574                 Mem_Free(basepixels);
3575
3576         return skinframe;
3577 }
3578
3579 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3580 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3581 {
3582         int i;
3583         skinframe_t *skinframe;
3584         char vabuf[1024];
3585
3586         if (cls.state == ca_dedicated)
3587                 return NULL;
3588
3589         // if already loaded just return it, otherwise make a new skinframe
3590         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3591         if (skinframe->base)
3592                 return skinframe;
3593         textureflags &= ~TEXF_FORCE_RELOAD;
3594
3595         skinframe->stain = NULL;
3596         skinframe->merged = NULL;
3597         skinframe->base = NULL;
3598         skinframe->pants = NULL;
3599         skinframe->shirt = NULL;
3600         skinframe->nmap = NULL;
3601         skinframe->gloss = NULL;
3602         skinframe->glow = NULL;
3603         skinframe->fog = NULL;
3604         skinframe->reflect = NULL;
3605         skinframe->hasalpha = false;
3606
3607         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3608         if (!skindata)
3609                 return NULL;
3610
3611         if (developer_loading.integer)
3612                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3613
3614         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3615         {
3616                 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3617                 unsigned char *b = a + width * height * 4;
3618                 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3619                 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);
3620                 Mem_Free(a);
3621         }
3622         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3623         if (textureflags & TEXF_ALPHA)
3624         {
3625                 for (i = 3;i < width * height * 4;i += 4)
3626                 {
3627                         if (skindata[i] < 255)
3628                         {
3629                                 skinframe->hasalpha = true;
3630                                 break;
3631                         }
3632                 }
3633                 if (r_loadfog && skinframe->hasalpha)
3634                 {
3635                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3636                         memcpy(fogpixels, skindata, width * height * 4);
3637                         for (i = 0;i < width * height * 4;i += 4)
3638                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3639                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3640                         Mem_Free(fogpixels);
3641                 }
3642         }
3643
3644         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3645         //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]);
3646
3647         return skinframe;
3648 }
3649
3650 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3651 {
3652         int i;
3653         int featuresmask;
3654         skinframe_t *skinframe;
3655
3656         if (cls.state == ca_dedicated)
3657                 return NULL;
3658
3659         // if already loaded just return it, otherwise make a new skinframe
3660         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3661         if (skinframe->base)
3662                 return skinframe;
3663         //textureflags &= ~TEXF_FORCE_RELOAD;
3664
3665         skinframe->stain = NULL;
3666         skinframe->merged = NULL;
3667         skinframe->base = NULL;
3668         skinframe->pants = NULL;
3669         skinframe->shirt = NULL;
3670         skinframe->nmap = NULL;
3671         skinframe->gloss = NULL;
3672         skinframe->glow = NULL;
3673         skinframe->fog = NULL;
3674         skinframe->reflect = NULL;
3675         skinframe->hasalpha = false;
3676
3677         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3678         if (!skindata)
3679                 return NULL;
3680
3681         if (developer_loading.integer)
3682                 Con_Printf("loading quake skin \"%s\"\n", name);
3683
3684         // 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)
3685         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3686         memcpy(skinframe->qpixels, skindata, width*height);
3687         skinframe->qwidth = width;
3688         skinframe->qheight = height;
3689
3690         featuresmask = 0;
3691         for (i = 0;i < width * height;i++)
3692                 featuresmask |= palette_featureflags[skindata[i]];
3693
3694         skinframe->hasalpha = false;
3695         // fence textures
3696         if (name[0] == '{')
3697                 skinframe->hasalpha = true;
3698         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3699         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3700         skinframe->qgeneratemerged = true;
3701         skinframe->qgeneratebase = skinframe->qhascolormapping;
3702         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3703
3704         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3705         //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]);
3706
3707         return skinframe;
3708 }
3709
3710 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3711 {
3712         int width;
3713         int height;
3714         unsigned char *skindata;
3715         char vabuf[1024];
3716
3717         if (!skinframe->qpixels)
3718                 return;
3719
3720         if (!skinframe->qhascolormapping)
3721                 colormapped = false;
3722
3723         if (colormapped)
3724         {
3725                 if (!skinframe->qgeneratebase)
3726                         return;
3727         }
3728         else
3729         {
3730                 if (!skinframe->qgeneratemerged)
3731                         return;
3732         }
3733
3734         width = skinframe->qwidth;
3735         height = skinframe->qheight;
3736         skindata = skinframe->qpixels;
3737
3738         if (skinframe->qgeneratenmap)
3739         {
3740                 unsigned char *a, *b;
3741                 skinframe->qgeneratenmap = false;
3742                 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3743                 b = a + width * height * 4;
3744                 // use either a custom palette or the quake palette
3745                 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3746                 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3747                 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);
3748                 Mem_Free(a);
3749         }
3750
3751         if (skinframe->qgenerateglow)
3752         {
3753                 skinframe->qgenerateglow = false;
3754                 if (skinframe->hasalpha) // fence textures
3755                         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
3756                 else
3757                         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
3758         }
3759
3760         if (colormapped)
3761         {
3762                 skinframe->qgeneratebase = false;
3763                 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);
3764                 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);
3765                 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);
3766         }
3767         else
3768         {
3769                 skinframe->qgeneratemerged = false;
3770                 if (skinframe->hasalpha) // fence textures
3771                         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);
3772                 else
3773                         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);
3774         }
3775
3776         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3777         {
3778                 Mem_Free(skinframe->qpixels);
3779                 skinframe->qpixels = NULL;
3780         }
3781 }
3782
3783 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)
3784 {
3785         int i;
3786         skinframe_t *skinframe;
3787         char vabuf[1024];
3788
3789         if (cls.state == ca_dedicated)
3790                 return NULL;
3791
3792         // if already loaded just return it, otherwise make a new skinframe
3793         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3794         if (skinframe->base)
3795                 return skinframe;
3796         textureflags &= ~TEXF_FORCE_RELOAD;
3797
3798         skinframe->stain = NULL;
3799         skinframe->merged = NULL;
3800         skinframe->base = NULL;
3801         skinframe->pants = NULL;
3802         skinframe->shirt = NULL;
3803         skinframe->nmap = NULL;
3804         skinframe->gloss = NULL;
3805         skinframe->glow = NULL;
3806         skinframe->fog = NULL;
3807         skinframe->reflect = NULL;
3808         skinframe->hasalpha = false;
3809
3810         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3811         if (!skindata)
3812                 return NULL;
3813
3814         if (developer_loading.integer)
3815                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3816
3817         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3818         if (textureflags & TEXF_ALPHA)
3819         {
3820                 for (i = 0;i < width * height;i++)
3821                 {
3822                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3823                         {
3824                                 skinframe->hasalpha = true;
3825                                 break;
3826                         }
3827                 }
3828                 if (r_loadfog && skinframe->hasalpha)
3829                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3830         }
3831
3832         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3833         //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]);
3834
3835         return skinframe;
3836 }
3837
3838 skinframe_t *R_SkinFrame_LoadMissing(void)
3839 {
3840         skinframe_t *skinframe;
3841
3842         if (cls.state == ca_dedicated)
3843                 return NULL;
3844
3845         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3846         skinframe->stain = NULL;
3847         skinframe->merged = NULL;
3848         skinframe->base = NULL;
3849         skinframe->pants = NULL;
3850         skinframe->shirt = NULL;
3851         skinframe->nmap = NULL;
3852         skinframe->gloss = NULL;
3853         skinframe->glow = NULL;
3854         skinframe->fog = NULL;
3855         skinframe->reflect = NULL;
3856         skinframe->hasalpha = false;
3857
3858         skinframe->avgcolor[0] = rand() / RAND_MAX;
3859         skinframe->avgcolor[1] = rand() / RAND_MAX;
3860         skinframe->avgcolor[2] = rand() / RAND_MAX;
3861         skinframe->avgcolor[3] = 1;
3862
3863         return skinframe;
3864 }
3865
3866 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3867 typedef struct suffixinfo_s
3868 {
3869         const char *suffix;
3870         qboolean flipx, flipy, flipdiagonal;
3871 }
3872 suffixinfo_t;
3873 static suffixinfo_t suffix[3][6] =
3874 {
3875         {
3876                 {"px",   false, false, false},
3877                 {"nx",   false, false, false},
3878                 {"py",   false, false, false},
3879                 {"ny",   false, false, false},
3880                 {"pz",   false, false, false},
3881                 {"nz",   false, false, false}
3882         },
3883         {
3884                 {"posx", false, false, false},
3885                 {"negx", false, false, false},
3886                 {"posy", false, false, false},
3887                 {"negy", false, false, false},
3888                 {"posz", false, false, false},
3889                 {"negz", false, false, false}
3890         },
3891         {
3892                 {"rt",    true, false,  true},
3893                 {"lf",   false,  true,  true},
3894                 {"ft",    true,  true, false},
3895                 {"bk",   false, false, false},
3896                 {"up",    true, false,  true},
3897                 {"dn",    true, false,  true}
3898         }
3899 };
3900
3901 static int componentorder[4] = {0, 1, 2, 3};
3902
3903 static rtexture_t *R_LoadCubemap(const char *basename)
3904 {
3905         int i, j, cubemapsize;
3906         unsigned char *cubemappixels, *image_buffer;
3907         rtexture_t *cubemaptexture;
3908         char name[256];
3909         // must start 0 so the first loadimagepixels has no requested width/height
3910         cubemapsize = 0;
3911         cubemappixels = NULL;
3912         cubemaptexture = NULL;
3913         // keep trying different suffix groups (posx, px, rt) until one loads
3914         for (j = 0;j < 3 && !cubemappixels;j++)
3915         {
3916                 // load the 6 images in the suffix group
3917                 for (i = 0;i < 6;i++)
3918                 {
3919                         // generate an image name based on the base and and suffix
3920                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3921                         // load it
3922                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3923                         {
3924                                 // an image loaded, make sure width and height are equal
3925                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3926                                 {
3927                                         // if this is the first image to load successfully, allocate the cubemap memory
3928                                         if (!cubemappixels && image_width >= 1)
3929                                         {
3930                                                 cubemapsize = image_width;
3931                                                 // note this clears to black, so unavailable sides are black
3932                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3933                                         }
3934                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3935                                         if (cubemappixels)
3936                                                 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);
3937                                 }
3938                                 else
3939                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3940                                 // free the image
3941                                 Mem_Free(image_buffer);
3942                         }
3943                 }
3944         }
3945         // if a cubemap loaded, upload it
3946         if (cubemappixels)
3947         {
3948                 if (developer_loading.integer)
3949                         Con_Printf("loading cubemap \"%s\"\n", basename);
3950
3951                 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);
3952                 Mem_Free(cubemappixels);
3953         }
3954         else
3955         {
3956                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3957                 if (developer_loading.integer)
3958                 {
3959                         Con_Printf("(tried tried images ");
3960                         for (j = 0;j < 3;j++)
3961                                 for (i = 0;i < 6;i++)
3962                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3963                         Con_Print(" and was unable to find any of them).\n");
3964                 }
3965         }
3966         return cubemaptexture;
3967 }
3968
3969 rtexture_t *R_GetCubemap(const char *basename)
3970 {
3971         int i;
3972         for (i = 0;i < r_texture_numcubemaps;i++)
3973                 if (r_texture_cubemaps[i] != NULL)
3974                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3975                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3976         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3977                 return r_texture_whitecube;
3978         r_texture_numcubemaps++;
3979         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3980         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3981         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3982         return r_texture_cubemaps[i]->texture;
3983 }
3984
3985 static void R_Main_FreeViewCache(void)
3986 {
3987         if (r_refdef.viewcache.entityvisible)
3988                 Mem_Free(r_refdef.viewcache.entityvisible);
3989         if (r_refdef.viewcache.world_pvsbits)
3990                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3991         if (r_refdef.viewcache.world_leafvisible)
3992                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3993         if (r_refdef.viewcache.world_surfacevisible)
3994                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3995         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3996 }
3997
3998 static void R_Main_ResizeViewCache(void)
3999 {
4000         int numentities = r_refdef.scene.numentities;
4001         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4002         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4003         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4004         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4005         if (r_refdef.viewcache.maxentities < numentities)
4006         {
4007                 r_refdef.viewcache.maxentities = numentities;
4008                 if (r_refdef.viewcache.entityvisible)
4009                         Mem_Free(r_refdef.viewcache.entityvisible);
4010                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4011         }
4012         if (r_refdef.viewcache.world_numclusters != numclusters)
4013         {
4014                 r_refdef.viewcache.world_numclusters = numclusters;
4015                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4016                 if (r_refdef.viewcache.world_pvsbits)
4017                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4018                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4019         }
4020         if (r_refdef.viewcache.world_numleafs != numleafs)
4021         {
4022                 r_refdef.viewcache.world_numleafs = numleafs;
4023                 if (r_refdef.viewcache.world_leafvisible)
4024                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4025                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4026         }
4027         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4028         {
4029                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4030                 if (r_refdef.viewcache.world_surfacevisible)
4031                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4032                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4033         }
4034 }
4035
4036 extern rtexture_t *loadingscreentexture;
4037 static void gl_main_start(void)
4038 {
4039         loadingscreentexture = NULL;
4040         r_texture_blanknormalmap = NULL;
4041         r_texture_white = NULL;
4042         r_texture_grey128 = NULL;
4043         r_texture_black = NULL;
4044         r_texture_whitecube = NULL;
4045         r_texture_normalizationcube = NULL;
4046         r_texture_fogattenuation = NULL;
4047         r_texture_fogheighttexture = NULL;
4048         r_texture_gammaramps = NULL;
4049         r_texture_numcubemaps = 0;
4050         r_uniformbufferalignment = 32;
4051
4052         r_loaddds = r_texture_dds_load.integer != 0;
4053         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4054
4055         switch(vid.renderpath)
4056         {
4057         case RENDERPATH_GL20:
4058         case RENDERPATH_D3D9:
4059         case RENDERPATH_D3D10:
4060         case RENDERPATH_D3D11:
4061         case RENDERPATH_SOFT:
4062         case RENDERPATH_GLES2:
4063                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4064                 Cvar_SetValueQuick(&gl_combine, 1);
4065                 Cvar_SetValueQuick(&r_glsl, 1);
4066                 r_loadnormalmap = true;
4067                 r_loadgloss = true;
4068                 r_loadfog = false;
4069 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4070                 if (vid.support.arb_uniform_buffer_object)
4071                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4072 #endif
4073                         break;
4074         case RENDERPATH_GL13:
4075         case RENDERPATH_GLES1:
4076                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4077                 Cvar_SetValueQuick(&gl_combine, 1);
4078                 Cvar_SetValueQuick(&r_glsl, 0);
4079                 r_loadnormalmap = false;
4080                 r_loadgloss = false;
4081                 r_loadfog = true;
4082                 break;
4083         case RENDERPATH_GL11:
4084                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4085                 Cvar_SetValueQuick(&gl_combine, 0);
4086                 Cvar_SetValueQuick(&r_glsl, 0);
4087                 r_loadnormalmap = false;
4088                 r_loadgloss = false;
4089                 r_loadfog = true;
4090                 break;
4091         }
4092
4093         R_AnimCache_Free();
4094         R_FrameData_Reset();
4095         R_BufferData_Reset();
4096
4097         r_numqueries = 0;
4098         r_maxqueries = 0;
4099         memset(r_queries, 0, sizeof(r_queries));
4100
4101         r_qwskincache = NULL;
4102         r_qwskincache_size = 0;
4103
4104         // due to caching of texture_t references, the collision cache must be reset
4105         Collision_Cache_Reset(true);
4106
4107         // set up r_skinframe loading system for textures
4108         memset(&r_skinframe, 0, sizeof(r_skinframe));
4109         r_skinframe.loadsequence = 1;
4110         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4111
4112         r_main_texturepool = R_AllocTexturePool();
4113         R_BuildBlankTextures();
4114         R_BuildNoTexture();
4115         if (vid.support.arb_texture_cube_map)
4116         {
4117                 R_BuildWhiteCube();
4118                 R_BuildNormalizationCube();
4119         }
4120         r_texture_fogattenuation = NULL;
4121         r_texture_fogheighttexture = NULL;
4122         r_texture_gammaramps = NULL;
4123         //r_texture_fogintensity = NULL;
4124         memset(&r_fb, 0, sizeof(r_fb));
4125         r_glsl_permutation = NULL;
4126         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4127         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4128         glslshaderstring = NULL;
4129 #ifdef SUPPORTD3D
4130         r_hlsl_permutation = NULL;
4131         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4132         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4133 #endif
4134         hlslshaderstring = NULL;
4135         memset(&r_svbsp, 0, sizeof (r_svbsp));
4136
4137         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4138         r_texture_numcubemaps = 0;
4139
4140         r_refdef.fogmasktable_density = 0;
4141
4142 #ifdef __ANDROID__
4143         // For Steelstorm Android
4144         // FIXME CACHE the program and reload
4145         // FIXME see possible combinations for SS:BR android
4146         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4147         R_SetupShader_SetPermutationGLSL(0, 12);
4148         R_SetupShader_SetPermutationGLSL(0, 13);
4149         R_SetupShader_SetPermutationGLSL(0, 8388621);
4150         R_SetupShader_SetPermutationGLSL(3, 0);
4151         R_SetupShader_SetPermutationGLSL(3, 2048);
4152         R_SetupShader_SetPermutationGLSL(5, 0);
4153         R_SetupShader_SetPermutationGLSL(5, 2);
4154         R_SetupShader_SetPermutationGLSL(5, 2048);
4155         R_SetupShader_SetPermutationGLSL(5, 8388608);
4156         R_SetupShader_SetPermutationGLSL(11, 1);
4157         R_SetupShader_SetPermutationGLSL(11, 2049);
4158         R_SetupShader_SetPermutationGLSL(11, 8193);
4159         R_SetupShader_SetPermutationGLSL(11, 10241);
4160         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4161 #endif
4162 }
4163
4164 static void gl_main_shutdown(void)
4165 {
4166         R_AnimCache_Free();
4167         R_FrameData_Reset();
4168         R_BufferData_Reset();
4169
4170         R_Main_FreeViewCache();
4171
4172         switch(vid.renderpath)
4173         {
4174         case RENDERPATH_GL11:
4175         case RENDERPATH_GL13:
4176         case RENDERPATH_GL20:
4177         case RENDERPATH_GLES1:
4178         case RENDERPATH_GLES2:
4179 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4180                 if (r_maxqueries)
4181                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4182 #endif
4183                 break;
4184         case RENDERPATH_D3D9:
4185                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4186                 break;
4187         case RENDERPATH_D3D10:
4188                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4189                 break;
4190         case RENDERPATH_D3D11:
4191                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4192                 break;
4193         case RENDERPATH_SOFT:
4194                 break;
4195         }
4196
4197         r_numqueries = 0;
4198         r_maxqueries = 0;
4199         memset(r_queries, 0, sizeof(r_queries));
4200
4201         r_qwskincache = NULL;
4202         r_qwskincache_size = 0;
4203
4204         // clear out the r_skinframe state
4205         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4206         memset(&r_skinframe, 0, sizeof(r_skinframe));
4207
4208         if (r_svbsp.nodes)
4209                 Mem_Free(r_svbsp.nodes);
4210         memset(&r_svbsp, 0, sizeof (r_svbsp));
4211         R_FreeTexturePool(&r_main_texturepool);
4212         loadingscreentexture = NULL;
4213         r_texture_blanknormalmap = NULL;
4214         r_texture_white = NULL;
4215         r_texture_grey128 = NULL;
4216         r_texture_black = NULL;
4217         r_texture_whitecube = NULL;
4218         r_texture_normalizationcube = NULL;
4219         r_texture_fogattenuation = NULL;
4220         r_texture_fogheighttexture = NULL;
4221         r_texture_gammaramps = NULL;
4222         r_texture_numcubemaps = 0;
4223         //r_texture_fogintensity = NULL;
4224         memset(&r_fb, 0, sizeof(r_fb));
4225         R_GLSL_Restart_f();
4226
4227         r_glsl_permutation = NULL;
4228         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4229         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4230         glslshaderstring = NULL;
4231 #ifdef SUPPORTD3D
4232         r_hlsl_permutation = NULL;
4233         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4234         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4235 #endif
4236         hlslshaderstring = NULL;
4237 }
4238
4239 static void gl_main_newmap(void)
4240 {
4241         // FIXME: move this code to client
4242         char *entities, entname[MAX_QPATH];
4243         if (r_qwskincache)
4244                 Mem_Free(r_qwskincache);
4245         r_qwskincache = NULL;
4246         r_qwskincache_size = 0;
4247         if (cl.worldmodel)
4248         {
4249                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4250                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4251                 {
4252                         CL_ParseEntityLump(entities);
4253                         Mem_Free(entities);
4254                         return;
4255                 }
4256                 if (cl.worldmodel->brush.entities)
4257                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4258         }
4259         R_Main_FreeViewCache();
4260
4261         R_FrameData_Reset();
4262         R_BufferData_Reset();
4263 }
4264
4265 void GL_Main_Init(void)
4266 {
4267         int i;
4268         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4269
4270         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4271         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4272         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4273         if (gamemode == GAME_NEHAHRA)
4274         {
4275                 Cvar_RegisterVariable (&gl_fogenable);
4276                 Cvar_RegisterVariable (&gl_fogdensity);
4277                 Cvar_RegisterVariable (&gl_fogred);
4278                 Cvar_RegisterVariable (&gl_foggreen);
4279                 Cvar_RegisterVariable (&gl_fogblue);
4280                 Cvar_RegisterVariable (&gl_fogstart);
4281                 Cvar_RegisterVariable (&gl_fogend);
4282                 Cvar_RegisterVariable (&gl_skyclip);
4283         }
4284         Cvar_RegisterVariable(&r_motionblur);
4285         Cvar_RegisterVariable(&r_damageblur);
4286         Cvar_RegisterVariable(&r_motionblur_averaging);
4287         Cvar_RegisterVariable(&r_motionblur_randomize);
4288         Cvar_RegisterVariable(&r_motionblur_minblur);
4289         Cvar_RegisterVariable(&r_motionblur_maxblur);
4290         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4291         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4292         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4293         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4294         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4295         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4296         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4297         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4298         Cvar_RegisterVariable(&r_equalize_entities_by);
4299         Cvar_RegisterVariable(&r_equalize_entities_to);
4300         Cvar_RegisterVariable(&r_depthfirst);
4301         Cvar_RegisterVariable(&r_useinfinitefarclip);
4302         Cvar_RegisterVariable(&r_farclip_base);
4303         Cvar_RegisterVariable(&r_farclip_world);
4304         Cvar_RegisterVariable(&r_nearclip);
4305         Cvar_RegisterVariable(&r_deformvertexes);
4306         Cvar_RegisterVariable(&r_transparent);
4307         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4308         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4309         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4310         Cvar_RegisterVariable(&r_showoverdraw);
4311         Cvar_RegisterVariable(&r_showbboxes);
4312         Cvar_RegisterVariable(&r_showsurfaces);
4313         Cvar_RegisterVariable(&r_showtris);
4314         Cvar_RegisterVariable(&r_shownormals);
4315         Cvar_RegisterVariable(&r_showlighting);
4316         Cvar_RegisterVariable(&r_showshadowvolumes);
4317         Cvar_RegisterVariable(&r_showcollisionbrushes);
4318         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4319         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4320         Cvar_RegisterVariable(&r_showdisabledepthtest);
4321         Cvar_RegisterVariable(&r_drawportals);
4322         Cvar_RegisterVariable(&r_drawentities);
4323         Cvar_RegisterVariable(&r_draw2d);
4324         Cvar_RegisterVariable(&r_drawworld);
4325         Cvar_RegisterVariable(&r_cullentities_trace);
4326         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4327         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4328         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4329         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4330         Cvar_RegisterVariable(&r_sortentities);
4331         Cvar_RegisterVariable(&r_drawviewmodel);
4332         Cvar_RegisterVariable(&r_drawexteriormodel);
4333         Cvar_RegisterVariable(&r_speeds);
4334         Cvar_RegisterVariable(&r_fullbrights);
4335         Cvar_RegisterVariable(&r_wateralpha);
4336         Cvar_RegisterVariable(&r_dynamic);
4337         Cvar_RegisterVariable(&r_fakelight);
4338         Cvar_RegisterVariable(&r_fakelight_intensity);
4339         Cvar_RegisterVariable(&r_fullbright);
4340         Cvar_RegisterVariable(&r_shadows);
4341         Cvar_RegisterVariable(&r_shadows_darken);
4342         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4343         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4344         Cvar_RegisterVariable(&r_shadows_throwdistance);
4345         Cvar_RegisterVariable(&r_shadows_throwdirection);
4346         Cvar_RegisterVariable(&r_shadows_focus);
4347         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4348         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4349         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4350         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4351         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4352         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4353         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4354         Cvar_RegisterVariable(&r_fog_exp2);
4355         Cvar_RegisterVariable(&r_fog_clear);
4356         Cvar_RegisterVariable(&r_drawfog);
4357         Cvar_RegisterVariable(&r_transparentdepthmasking);
4358         Cvar_RegisterVariable(&r_transparent_sortmindist);
4359         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4360         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4361         Cvar_RegisterVariable(&r_texture_dds_load);
4362         Cvar_RegisterVariable(&r_texture_dds_save);
4363         Cvar_RegisterVariable(&r_textureunits);
4364         Cvar_RegisterVariable(&gl_combine);
4365         Cvar_RegisterVariable(&r_usedepthtextures);
4366         Cvar_RegisterVariable(&r_viewfbo);
4367         Cvar_RegisterVariable(&r_viewscale);
4368         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4369         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4370         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4371         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4372         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4373         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4374         Cvar_RegisterVariable(&r_glsl);
4375         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4376         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4377         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4378         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4379         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4380         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4381         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4382         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4383         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4384         Cvar_RegisterVariable(&r_glsl_postprocess);
4385         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4386         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4387         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4388         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4389         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4390         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4391         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4392         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4393         Cvar_RegisterVariable(&r_celshading);
4394         Cvar_RegisterVariable(&r_celoutlines);
4395
4396         Cvar_RegisterVariable(&r_water);
4397         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4398         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4399         Cvar_RegisterVariable(&r_water_clippingplanebias);
4400         Cvar_RegisterVariable(&r_water_refractdistort);
4401         Cvar_RegisterVariable(&r_water_reflectdistort);
4402         Cvar_RegisterVariable(&r_water_scissormode);
4403         Cvar_RegisterVariable(&r_water_lowquality);
4404         Cvar_RegisterVariable(&r_water_hideplayer);
4405         Cvar_RegisterVariable(&r_water_fbo);
4406
4407         Cvar_RegisterVariable(&r_lerpsprites);
4408         Cvar_RegisterVariable(&r_lerpmodels);
4409         Cvar_RegisterVariable(&r_lerplightstyles);
4410         Cvar_RegisterVariable(&r_waterscroll);
4411         Cvar_RegisterVariable(&r_bloom);
4412         Cvar_RegisterVariable(&r_bloom_colorscale);
4413         Cvar_RegisterVariable(&r_bloom_brighten);
4414         Cvar_RegisterVariable(&r_bloom_blur);
4415         Cvar_RegisterVariable(&r_bloom_resolution);
4416         Cvar_RegisterVariable(&r_bloom_colorexponent);
4417         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4418         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4419         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4420         Cvar_RegisterVariable(&r_hdr_glowintensity);
4421         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4422         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4423         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4424         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4425         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4426         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4427         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4428         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4429         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4430         Cvar_RegisterVariable(&developer_texturelogging);
4431         Cvar_RegisterVariable(&gl_lightmaps);
4432         Cvar_RegisterVariable(&r_test);
4433         Cvar_RegisterVariable(&r_batch_multidraw);
4434         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4435         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4436         Cvar_RegisterVariable(&r_glsl_skeletal);
4437         Cvar_RegisterVariable(&r_glsl_saturation);
4438         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4439         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4440         Cvar_RegisterVariable(&r_framedatasize);
4441         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4442                 Cvar_RegisterVariable(&r_buffermegs[i]);
4443         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4444         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4445                 Cvar_SetValue("r_fullbrights", 0);
4446 #ifdef DP_MOBILETOUCH
4447         // GLES devices have terrible depth precision in general, so...
4448         Cvar_SetValueQuick(&r_nearclip, 4);
4449         Cvar_SetValueQuick(&r_farclip_base, 4096);
4450         Cvar_SetValueQuick(&r_farclip_world, 0);
4451         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4452 #endif
4453         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4454 }
4455
4456 void Render_Init(void)
4457 {
4458         gl_backend_init();
4459         R_Textures_Init();
4460         GL_Main_Init();
4461         Font_Init();
4462         GL_Draw_Init();
4463         R_Shadow_Init();
4464         R_Sky_Init();
4465         GL_Surf_Init();
4466         Sbar_Init();
4467         R_Particles_Init();
4468         R_Explosion_Init();
4469         R_LightningBeams_Init();
4470         Mod_RenderInit();
4471 }
4472
4473 /*
4474 ===============
4475 GL_Init
4476 ===============
4477 */
4478 #ifndef USE_GLES2
4479 extern char *ENGINE_EXTENSIONS;
4480 void GL_Init (void)
4481 {
4482         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4483         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4484         gl_version = (const char *)qglGetString(GL_VERSION);
4485         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4486
4487         if (!gl_extensions)
4488                 gl_extensions = "";
4489         if (!gl_platformextensions)
4490                 gl_platformextensions = "";
4491
4492         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4493         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4494         Con_Printf("GL_VERSION: %s\n", gl_version);
4495         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4496         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4497
4498         VID_CheckExtensions();
4499
4500         // LordHavoc: report supported extensions
4501 #ifdef CONFIG_MENU
4502         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4503 #else
4504         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4505 #endif
4506
4507         // clear to black (loading plaque will be seen over this)
4508         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4509 }
4510 #endif
4511
4512 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4513 {
4514         int i;
4515         mplane_t *p;
4516         if (r_trippy.integer)
4517                 return false;
4518         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4519         {
4520                 p = r_refdef.view.frustum + i;
4521                 switch(p->signbits)
4522                 {
4523                 default:
4524                 case 0:
4525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4526                                 return true;
4527                         break;
4528                 case 1:
4529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4530                                 return true;
4531                         break;
4532                 case 2:
4533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4534                                 return true;
4535                         break;
4536                 case 3:
4537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4538                                 return true;
4539                         break;
4540                 case 4:
4541                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4542                                 return true;
4543                         break;
4544                 case 5:
4545                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4546                                 return true;
4547                         break;
4548                 case 6:
4549                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4550                                 return true;
4551                         break;
4552                 case 7:
4553                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4554                                 return true;
4555                         break;
4556                 }
4557         }
4558         return false;
4559 }
4560
4561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4562 {
4563         int i;
4564         const mplane_t *p;
4565         if (r_trippy.integer)
4566                 return false;
4567         for (i = 0;i < numplanes;i++)
4568         {
4569                 p = planes + i;
4570                 switch(p->signbits)
4571                 {
4572                 default:
4573                 case 0:
4574                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4575                                 return true;
4576                         break;
4577                 case 1:
4578                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4579                                 return true;
4580                         break;
4581                 case 2:
4582                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4583                                 return true;
4584                         break;
4585                 case 3:
4586                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4587                                 return true;
4588                         break;
4589                 case 4:
4590                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4591                                 return true;
4592                         break;
4593                 case 5:
4594                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4595                                 return true;
4596                         break;
4597                 case 6:
4598                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4599                                 return true;
4600                         break;
4601                 case 7:
4602                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4603                                 return true;
4604                         break;
4605                 }
4606         }
4607         return false;
4608 }
4609
4610 //==================================================================================
4611
4612 // LordHavoc: this stores temporary data used within the same frame
4613
4614 typedef struct r_framedata_mem_s
4615 {
4616         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4617         size_t size; // how much usable space
4618         size_t current; // how much space in use
4619         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4620         size_t wantedsize; // how much space was allocated
4621         unsigned char *data; // start of real data (16byte aligned)
4622 }
4623 r_framedata_mem_t;
4624
4625 static r_framedata_mem_t *r_framedata_mem;
4626
4627 void R_FrameData_Reset(void)
4628 {
4629         while (r_framedata_mem)
4630         {
4631                 r_framedata_mem_t *next = r_framedata_mem->purge;
4632                 Mem_Free(r_framedata_mem);
4633                 r_framedata_mem = next;
4634         }
4635 }
4636
4637 static void R_FrameData_Resize(qboolean mustgrow)
4638 {
4639         size_t wantedsize;
4640         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4641         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4642         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4643         {
4644                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4645                 newmem->wantedsize = wantedsize;
4646                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4647                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4648                 newmem->current = 0;
4649                 newmem->mark = 0;
4650                 newmem->purge = r_framedata_mem;
4651                 r_framedata_mem = newmem;
4652         }
4653 }
4654
4655 void R_FrameData_NewFrame(void)
4656 {
4657         R_FrameData_Resize(false);
4658         if (!r_framedata_mem)
4659                 return;
4660         // if we ran out of space on the last frame, free the old memory now
4661         while (r_framedata_mem->purge)
4662         {
4663                 // repeatedly remove the second item in the list, leaving only head
4664                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4665                 Mem_Free(r_framedata_mem->purge);
4666                 r_framedata_mem->purge = next;
4667         }
4668         // reset the current mem pointer
4669         r_framedata_mem->current = 0;
4670         r_framedata_mem->mark = 0;
4671 }
4672
4673 void *R_FrameData_Alloc(size_t size)
4674 {
4675         void *data;
4676         float newvalue;
4677
4678         // align to 16 byte boundary - the data pointer is already aligned, so we
4679         // only need to ensure the size of every allocation is also aligned
4680         size = (size + 15) & ~15;
4681
4682         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4683         {
4684                 // emergency - we ran out of space, allocate more memory
4685                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4686                 // this might not be a growing it, but we'll allocate another buffer every time
4687                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4688                 R_FrameData_Resize(true);
4689         }
4690
4691         data = r_framedata_mem->data + r_framedata_mem->current;
4692         r_framedata_mem->current += size;
4693
4694         // count the usage for stats
4695         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4696         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4697
4698         return (void *)data;
4699 }
4700
4701 void *R_FrameData_Store(size_t size, void *data)
4702 {
4703         void *d = R_FrameData_Alloc(size);
4704         if (d && data)
4705                 memcpy(d, data, size);
4706         return d;
4707 }
4708
4709 void R_FrameData_SetMark(void)
4710 {
4711         if (!r_framedata_mem)
4712                 return;
4713         r_framedata_mem->mark = r_framedata_mem->current;
4714 }
4715
4716 void R_FrameData_ReturnToMark(void)
4717 {
4718         if (!r_framedata_mem)
4719                 return;
4720         r_framedata_mem->current = r_framedata_mem->mark;
4721 }
4722
4723 //==================================================================================
4724
4725 // avoid reusing the same buffer objects on consecutive frames
4726 #define R_BUFFERDATA_CYCLE 3
4727
4728 typedef struct r_bufferdata_buffer_s
4729 {
4730         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4731         size_t size; // how much usable space
4732         size_t current; // how much space in use
4733         r_meshbuffer_t *buffer; // the buffer itself
4734 }
4735 r_bufferdata_buffer_t;
4736
4737 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4738 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4739
4740 /// frees all dynamic buffers
4741 void R_BufferData_Reset(void)
4742 {
4743         int cycle, type;
4744         r_bufferdata_buffer_t **p, *mem;
4745         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4746         {
4747                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4748                 {
4749                         // free all buffers
4750                         p = &r_bufferdata_buffer[cycle][type];
4751                         while (*p)
4752                         {
4753                                 mem = *p;
4754                                 *p = (*p)->purge;
4755                                 if (mem->buffer)
4756                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4757                                 Mem_Free(mem);
4758                         }
4759                 }
4760         }
4761 }
4762
4763 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4764 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4765 {
4766         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4767         size_t size;
4768         float newvalue = r_buffermegs[type].value;
4769
4770         // increase the cvar if we have to (but only if we already have a mem)
4771         if (mustgrow && mem)
4772                 newvalue *= 2.0f;
4773         newvalue = bound(0.25f, newvalue, 256.0f);
4774         while (newvalue * 1024*1024 < minsize)
4775                 newvalue *= 2.0f;
4776
4777         // clamp the cvar to valid range
4778         newvalue = bound(0.25f, newvalue, 256.0f);
4779         if (r_buffermegs[type].value != newvalue)
4780                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4781
4782         // calculate size in bytes
4783         size = (size_t)(newvalue * 1024*1024);
4784         size = bound(131072, size, 256*1024*1024);
4785
4786         // allocate a new buffer if the size is different (purge old one later)
4787         // or if we were told we must grow the buffer
4788         if (!mem || mem->size != size || mustgrow)
4789         {
4790                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4791                 mem->size = size;
4792                 mem->current = 0;
4793                 if (type == R_BUFFERDATA_VERTEX)
4794                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4795                 else if (type == R_BUFFERDATA_INDEX16)
4796                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4797                 else if (type == R_BUFFERDATA_INDEX32)
4798                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4799                 else if (type == R_BUFFERDATA_UNIFORM)
4800                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4801                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4802                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4803         }
4804 }
4805
4806 void R_BufferData_NewFrame(void)
4807 {
4808         int type;
4809         r_bufferdata_buffer_t **p, *mem;
4810         // cycle to the next frame's buffers
4811         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4812         // if we ran out of space on the last time we used these buffers, free the old memory now
4813         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4814         {
4815                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4816                 {
4817                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4818                         // free all but the head buffer, this is how we recycle obsolete
4819                         // buffers after they are no longer in use
4820                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4821                         while (*p)
4822                         {
4823                                 mem = *p;
4824                                 *p = (*p)->purge;
4825                                 if (mem->buffer)
4826                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4827                                 Mem_Free(mem);
4828                         }
4829                         // reset the current offset
4830                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4831                 }
4832         }
4833 }
4834
4835 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4836 {
4837         r_bufferdata_buffer_t *mem;
4838         int offset = 0;
4839         int padsize;
4840
4841         *returnbufferoffset = 0;
4842
4843         // align size to a byte boundary appropriate for the buffer type, this
4844         // makes all allocations have aligned start offsets
4845         if (type == R_BUFFERDATA_UNIFORM)
4846                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4847         else
4848                 padsize = (datasize + 15) & ~15;
4849
4850         // if we ran out of space in this buffer we must allocate a new one
4851         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)
4852                 R_BufferData_Resize(type, true, padsize);
4853
4854         // if the resize did not give us enough memory, fail
4855         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)
4856                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4857
4858         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4859         offset = (int)mem->current;
4860         mem->current += padsize;
4861
4862         // upload the data to the buffer at the chosen offset
4863         if (offset == 0)
4864                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4865         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4866
4867         // count the usage for stats
4868         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4869         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4870
4871         // return the buffer offset
4872         *returnbufferoffset = offset;
4873
4874         return mem->buffer;
4875 }
4876
4877 //==================================================================================
4878
4879 // LordHavoc: animcache originally written by Echon, rewritten since then
4880
4881 /**
4882  * Animation cache prevents re-generating mesh data for an animated model
4883  * multiple times in one frame for lighting, shadowing, reflections, etc.
4884  */
4885
4886 void R_AnimCache_Free(void)
4887 {
4888 }
4889
4890 void R_AnimCache_ClearCache(void)
4891 {
4892         int i;
4893         entity_render_t *ent;
4894
4895         for (i = 0;i < r_refdef.scene.numentities;i++)
4896         {
4897                 ent = r_refdef.scene.entities[i];
4898                 ent->animcache_vertex3f = NULL;
4899                 ent->animcache_vertex3f_vertexbuffer = NULL;
4900                 ent->animcache_vertex3f_bufferoffset = 0;
4901                 ent->animcache_normal3f = NULL;
4902                 ent->animcache_normal3f_vertexbuffer = NULL;
4903                 ent->animcache_normal3f_bufferoffset = 0;
4904                 ent->animcache_svector3f = NULL;
4905                 ent->animcache_svector3f_vertexbuffer = NULL;
4906                 ent->animcache_svector3f_bufferoffset = 0;
4907                 ent->animcache_tvector3f = NULL;
4908                 ent->animcache_tvector3f_vertexbuffer = NULL;
4909                 ent->animcache_tvector3f_bufferoffset = 0;
4910                 ent->animcache_vertexmesh = NULL;
4911                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4912                 ent->animcache_vertexmesh_bufferoffset = 0;
4913                 ent->animcache_skeletaltransform3x4 = NULL;
4914                 ent->animcache_skeletaltransform3x4buffer = NULL;
4915                 ent->animcache_skeletaltransform3x4offset = 0;
4916                 ent->animcache_skeletaltransform3x4size = 0;
4917         }
4918 }
4919
4920 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4921 {
4922         int i;
4923
4924         // check if we need the meshbuffers
4925         if (!vid.useinterleavedarrays)
4926                 return;
4927
4928         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4929                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4930         // TODO: upload vertexbuffer?
4931         if (ent->animcache_vertexmesh)
4932         {
4933                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4934                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4935                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4936                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4937                 for (i = 0;i < numvertices;i++)
4938                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4939                 if (ent->animcache_svector3f)
4940                         for (i = 0;i < numvertices;i++)
4941                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4942                 if (ent->animcache_tvector3f)
4943                         for (i = 0;i < numvertices;i++)
4944                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4945                 if (ent->animcache_normal3f)
4946                         for (i = 0;i < numvertices;i++)
4947                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4948         }
4949 }
4950
4951 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4952 {
4953         dp_model_t *model = ent->model;
4954         int numvertices;
4955
4956         // see if this ent is worth caching
4957         if (!model || !model->Draw || !model->AnimateVertices)
4958                 return false;
4959         // nothing to cache if it contains no animations and has no skeleton
4960         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4961                 return false;
4962         // see if it is already cached for gpuskeletal
4963         if (ent->animcache_skeletaltransform3x4)
4964                 return false;
4965         // see if it is already cached as a mesh
4966         if (ent->animcache_vertex3f)
4967         {
4968                 // check if we need to add normals or tangents
4969                 if (ent->animcache_normal3f)
4970                         wantnormals = false;
4971                 if (ent->animcache_svector3f)
4972                         wanttangents = false;
4973                 if (!wantnormals && !wanttangents)
4974                         return false;
4975         }
4976
4977         // check which kind of cache we need to generate
4978         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4979         {
4980                 // cache the skeleton so the vertex shader can use it
4981                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4982                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4983                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4984                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4985                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4986                 // note: this can fail if the buffer is at the grow limit
4987                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4988                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4989         }
4990         else if (ent->animcache_vertex3f)
4991         {
4992                 // mesh was already cached but we may need to add normals/tangents
4993                 // (this only happens with multiple views, reflections, cameras, etc)
4994                 if (wantnormals || wanttangents)
4995                 {
4996                         numvertices = model->surfmesh.num_vertices;
4997                         if (wantnormals)
4998                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4999                         if (wanttangents)
5000                         {
5001                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5002                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5003                         }
5004                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5005                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5006                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5009                 }
5010         }
5011         else
5012         {
5013                 // generate mesh cache
5014                 numvertices = model->surfmesh.num_vertices;
5015                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5016                 if (wantnormals)
5017                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5018                 if (wanttangents)
5019                 {
5020                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5021                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5022                 }
5023                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5024                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5025                 if (wantnormals || wanttangents)
5026                 {
5027                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5028                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5029                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5030                 }
5031                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5032                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5033                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5034         }
5035         return true;
5036 }
5037
5038 void R_AnimCache_CacheVisibleEntities(void)
5039 {
5040         int i;
5041         qboolean wantnormals = true;
5042         qboolean wanttangents = !r_showsurfaces.integer;
5043
5044         switch(vid.renderpath)
5045         {
5046         case RENDERPATH_GL20:
5047         case RENDERPATH_D3D9:
5048         case RENDERPATH_D3D10:
5049         case RENDERPATH_D3D11:
5050         case RENDERPATH_GLES2:
5051                 break;
5052         case RENDERPATH_GL11:
5053         case RENDERPATH_GL13:
5054         case RENDERPATH_GLES1:
5055                 wanttangents = false;
5056                 break;
5057         case RENDERPATH_SOFT:
5058                 break;
5059         }
5060
5061         if (r_shownormals.integer)
5062                 wanttangents = wantnormals = true;
5063
5064         // TODO: thread this
5065         // NOTE: R_PrepareRTLights() also caches entities
5066
5067         for (i = 0;i < r_refdef.scene.numentities;i++)
5068                 if (r_refdef.viewcache.entityvisible[i])
5069                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5070 }
5071
5072 //==================================================================================
5073
5074 extern cvar_t r_overheadsprites_pushback;
5075
5076 static void R_View_UpdateEntityLighting (void)
5077 {
5078         int i;
5079         entity_render_t *ent;
5080         vec3_t tempdiffusenormal, avg;
5081         vec_t f, fa, fd, fdd;
5082         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5083
5084         for (i = 0;i < r_refdef.scene.numentities;i++)
5085         {
5086                 ent = r_refdef.scene.entities[i];
5087
5088                 // skip unseen models
5089                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5090                         continue;
5091
5092                 // skip bsp models
5093                 if (ent->model && ent->model == cl.worldmodel)
5094                 {
5095                         // TODO: use modellight for r_ambient settings on world?
5096                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5097                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5098                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5099                         continue;
5100                 }
5101                 
5102                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5103                 {
5104                         // aleady updated by CSQC
5105                         // TODO: force modellight on BSP models in this case?
5106                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5107                 }
5108                 else
5109                 {
5110                         // fetch the lighting from the worldmodel data
5111                         VectorClear(ent->modellight_ambient);
5112                         VectorClear(ent->modellight_diffuse);
5113                         VectorClear(tempdiffusenormal);
5114                         if (ent->flags & RENDER_LIGHT)
5115                         {
5116                                 vec3_t org;
5117                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5118
5119                                 // complete lightning for lit sprites
5120                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5121                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5122                                 {
5123                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5124                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5125                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5126                                 }
5127                                 else
5128                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5129
5130                                 if(ent->flags & RENDER_EQUALIZE)
5131                                 {
5132                                         // first fix up ambient lighting...
5133                                         if(r_equalize_entities_minambient.value > 0)
5134                                         {
5135                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5136                                                 if(fd > 0)
5137                                                 {
5138                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5139                                                         if(fa < r_equalize_entities_minambient.value * fd)
5140                                                         {
5141                                                                 // solve:
5142                                                                 //   fa'/fd' = minambient
5143                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5144                                                                 //   ...
5145                                                                 //   fa' = fd' * minambient
5146                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5147                                                                 //   ...
5148                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5149                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5150                                                                 //   ...
5151                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5152                                                                 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
5153                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5154                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5155                                                         }
5156                                                 }
5157                                         }
5158
5159                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5160                                         {
5161                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5162                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5163                                                 f = fa + 0.25 * fd;
5164                                                 if(f > 0)
5165                                                 {
5166                                                         // adjust brightness and saturation to target
5167                                                         avg[0] = avg[1] = avg[2] = fa / f;
5168                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5169                                                         avg[0] = avg[1] = avg[2] = fd / f;
5170                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5171                                                 }
5172                                         }
5173                                 }
5174                         }
5175                         else // highly rare
5176                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5177                 }
5178
5179                 // move the light direction into modelspace coordinates for lighting code
5180                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5181                 if(VectorLength2(ent->modellight_lightdir) == 0)
5182                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5183                 VectorNormalize(ent->modellight_lightdir);
5184         }
5185 }
5186
5187 #define MAX_LINEOFSIGHTTRACES 64
5188
5189 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5190 {
5191         int i;
5192         vec3_t boxmins, boxmaxs;
5193         vec3_t start;
5194         vec3_t end;
5195         dp_model_t *model = r_refdef.scene.worldmodel;
5196
5197         if (!model || !model->brush.TraceLineOfSight)
5198                 return true;
5199
5200         // expand the box a little
5201         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5202         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5203         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5204         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5205         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5206         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5207
5208         // return true if eye is inside enlarged box
5209         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5210                 return true;
5211
5212         // try center
5213         VectorCopy(eye, start);
5214         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5215         if (model->brush.TraceLineOfSight(model, start, end))
5216                 return true;
5217
5218         // try various random positions
5219         for (i = 0;i < numsamples;i++)
5220         {
5221                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5222                 if (model->brush.TraceLineOfSight(model, start, end))
5223                         return true;
5224         }
5225
5226         return false;
5227 }
5228
5229
5230 static void R_View_UpdateEntityVisible (void)
5231 {
5232         int i;
5233         int renderimask;
5234         int samples;
5235         entity_render_t *ent;
5236
5237         if (r_refdef.envmap || r_fb.water.hideplayer)
5238                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5239         else if (chase_active.integer || r_fb.water.renderingscene)
5240                 renderimask = RENDER_VIEWMODEL;
5241         else
5242                 renderimask = RENDER_EXTERIORMODEL;
5243         if (!r_drawviewmodel.integer)
5244                 renderimask |= RENDER_VIEWMODEL;
5245         if (!r_drawexteriormodel.integer)
5246                 renderimask |= RENDER_EXTERIORMODEL;
5247         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5248         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5249         {
5250                 // worldmodel can check visibility
5251                 for (i = 0;i < r_refdef.scene.numentities;i++)
5252                 {
5253                         ent = r_refdef.scene.entities[i];
5254                         if (!(ent->flags & renderimask))
5255                         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)))
5256                         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))
5257                                 r_refdef.viewcache.entityvisible[i] = true;
5258                 }
5259         }
5260         else
5261         {
5262                 // no worldmodel or it can't check visibility
5263                 for (i = 0;i < r_refdef.scene.numentities;i++)
5264                 {
5265                         ent = r_refdef.scene.entities[i];
5266                         if (!(ent->flags & renderimask))
5267                         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)))
5268                                 r_refdef.viewcache.entityvisible[i] = true;
5269                 }
5270         }
5271         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5272                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5273         {
5274                 for (i = 0;i < r_refdef.scene.numentities;i++)
5275                 {
5276                         if (!r_refdef.viewcache.entityvisible[i])
5277                                 continue;
5278                         ent = r_refdef.scene.entities[i];
5279                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5280                         {
5281                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5282                                 if (samples < 0)
5283                                         continue; // temp entities do pvs only
5284                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5285                                         ent->last_trace_visibility = realtime;
5286                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5287                                         r_refdef.viewcache.entityvisible[i] = 0;
5288                         }
5289                 }
5290         }
5291 }
5292
5293 /// only used if skyrendermasked, and normally returns false
5294 static int R_DrawBrushModelsSky (void)
5295 {
5296         int i, sky;
5297         entity_render_t *ent;
5298
5299         sky = false;
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->model || !ent->model->DrawSky)
5306                         continue;
5307                 ent->model->DrawSky(ent);
5308                 sky = true;
5309         }
5310         return sky;
5311 }
5312
5313 static void R_DrawNoModel(entity_render_t *ent);
5314 static void R_DrawModels(void)
5315 {
5316         int i;
5317         entity_render_t *ent;
5318
5319         for (i = 0;i < r_refdef.scene.numentities;i++)
5320         {
5321                 if (!r_refdef.viewcache.entityvisible[i])
5322                         continue;
5323                 ent = r_refdef.scene.entities[i];
5324                 r_refdef.stats[r_stat_entities]++;
5325                 /*
5326                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5327                 {
5328                         vec3_t f, l, u, o;
5329                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5330                         Con_Printf("R_DrawModels\n");
5331                         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]);
5332                         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);
5333                         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);
5334                 }
5335                 */
5336                 if (ent->model && ent->model->Draw != NULL)
5337                         ent->model->Draw(ent);
5338                 else
5339                         R_DrawNoModel(ent);
5340         }
5341 }
5342
5343 static void R_DrawModelsDepth(void)
5344 {
5345         int i;
5346         entity_render_t *ent;
5347
5348         for (i = 0;i < r_refdef.scene.numentities;i++)
5349         {
5350                 if (!r_refdef.viewcache.entityvisible[i])
5351                         continue;
5352                 ent = r_refdef.scene.entities[i];
5353                 if (ent->model && ent->model->DrawDepth != NULL)
5354                         ent->model->DrawDepth(ent);
5355         }
5356 }
5357
5358 static void R_DrawModelsDebug(void)
5359 {
5360         int i;
5361         entity_render_t *ent;
5362
5363         for (i = 0;i < r_refdef.scene.numentities;i++)
5364         {
5365                 if (!r_refdef.viewcache.entityvisible[i])
5366                         continue;
5367                 ent = r_refdef.scene.entities[i];
5368                 if (ent->model && ent->model->DrawDebug != NULL)
5369                         ent->model->DrawDebug(ent);
5370         }
5371 }
5372
5373 static void R_DrawModelsAddWaterPlanes(void)
5374 {
5375         int i;
5376         entity_render_t *ent;
5377
5378         for (i = 0;i < r_refdef.scene.numentities;i++)
5379         {
5380                 if (!r_refdef.viewcache.entityvisible[i])
5381                         continue;
5382                 ent = r_refdef.scene.entities[i];
5383                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5384                         ent->model->DrawAddWaterPlanes(ent);
5385         }
5386 }
5387
5388 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}};
5389
5390 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5391 {
5392         if (r_hdr_irisadaptation.integer)
5393         {
5394                 vec3_t p;
5395                 vec3_t ambient;
5396                 vec3_t diffuse;
5397                 vec3_t diffusenormal;
5398                 vec3_t forward;
5399                 vec_t brightness = 0.0f;
5400                 vec_t goal;
5401                 vec_t current;
5402                 vec_t d;
5403                 int c;
5404                 VectorCopy(r_refdef.view.forward, forward);
5405                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5406                 {
5407                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5408                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5409                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5410                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5411                         d = DotProduct(forward, diffusenormal);
5412                         brightness += VectorLength(ambient);
5413                         if (d > 0)
5414                                 brightness += d * VectorLength(diffuse);
5415                 }
5416                 brightness *= 1.0f / c;
5417                 brightness += 0.00001f; // make sure it's never zero
5418                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5419                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5420                 current = r_hdr_irisadaptation_value.value;
5421                 if (current < goal)
5422                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5423                 else if (current > goal)
5424                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5425                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5426                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5427         }
5428         else if (r_hdr_irisadaptation_value.value != 1.0f)
5429                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5430 }
5431
5432 static void R_View_SetFrustum(const int *scissor)
5433 {
5434         int i;
5435         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5436         vec3_t forward, left, up, origin, v;
5437
5438         if(scissor)
5439         {
5440                 // flipped x coordinates (because x points left here)
5441                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5442                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5443
5444                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5445                 switch(vid.renderpath)
5446                 {
5447                         case RENDERPATH_D3D9:
5448                         case RENDERPATH_D3D10:
5449                         case RENDERPATH_D3D11:
5450                                 // non-flipped y coordinates
5451                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5452                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5453                                 break;
5454                         case RENDERPATH_SOFT:
5455                         case RENDERPATH_GL11:
5456                         case RENDERPATH_GL13:
5457                         case RENDERPATH_GL20:
5458                         case RENDERPATH_GLES1:
5459                         case RENDERPATH_GLES2:
5460                                 // non-flipped y coordinates
5461                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5462                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5463                                 break;
5464                 }
5465         }
5466
5467         // we can't trust r_refdef.view.forward and friends in reflected scenes
5468         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5469
5470 #if 0
5471         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5472         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5473         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5474         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5475         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5476         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5477         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5478         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5479         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5480         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5481         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5482         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5483 #endif
5484
5485 #if 0
5486         zNear = r_refdef.nearclip;
5487         nudge = 1.0 - 1.0 / (1<<23);
5488         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5489         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5490         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5491         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5492         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5493         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5494         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5495         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5496 #endif
5497
5498
5499
5500 #if 0
5501         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5502         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5503         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5504         r_refdef.view.frustum[0].dist = m[15] - m[12];
5505
5506         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5507         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5508         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5509         r_refdef.view.frustum[1].dist = m[15] + m[12];
5510
5511         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5512         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5513         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5514         r_refdef.view.frustum[2].dist = m[15] - m[13];
5515
5516         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5517         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5518         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5519         r_refdef.view.frustum[3].dist = m[15] + m[13];
5520
5521         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5522         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5523         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5524         r_refdef.view.frustum[4].dist = m[15] - m[14];
5525
5526         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5527         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5528         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5529         r_refdef.view.frustum[5].dist = m[15] + m[14];
5530 #endif
5531
5532         if (r_refdef.view.useperspective)
5533         {
5534                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5535                 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]);
5536                 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]);
5537                 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]);
5538                 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]);
5539
5540                 // then the normals from the corners relative to origin
5541                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5542                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5543                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5544                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5545
5546                 // in a NORMAL view, forward cross left == up
5547                 // in a REFLECTED view, forward cross left == down
5548                 // so our cross products above need to be adjusted for a left handed coordinate system
5549                 CrossProduct(forward, left, v);
5550                 if(DotProduct(v, up) < 0)
5551                 {
5552                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5553                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5554                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5555                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5556                 }
5557
5558                 // Leaving those out was a mistake, those were in the old code, and they
5559                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5560                 // I couldn't reproduce it after adding those normalizations. --blub
5561                 VectorNormalize(r_refdef.view.frustum[0].normal);
5562                 VectorNormalize(r_refdef.view.frustum[1].normal);
5563                 VectorNormalize(r_refdef.view.frustum[2].normal);
5564                 VectorNormalize(r_refdef.view.frustum[3].normal);
5565
5566                 // make the corners absolute
5567                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5568                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5569                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5570                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5571
5572                 // one more normal
5573                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5574
5575                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5576                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5577                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5578                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5579                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5580         }
5581         else
5582         {
5583                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5584                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5585                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5586                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5587                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5588                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5589                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5590                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5591                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5592                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5593         }
5594         r_refdef.view.numfrustumplanes = 5;
5595
5596         if (r_refdef.view.useclipplane)
5597         {
5598                 r_refdef.view.numfrustumplanes = 6;
5599                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5600         }
5601
5602         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5603                 PlaneClassify(r_refdef.view.frustum + i);
5604
5605         // LordHavoc: note to all quake engine coders, Quake had a special case
5606         // for 90 degrees which assumed a square view (wrong), so I removed it,
5607         // Quake2 has it disabled as well.
5608
5609         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5610         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5611         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5612         //PlaneClassify(&frustum[0]);
5613
5614         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5615         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5616         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5617         //PlaneClassify(&frustum[1]);
5618
5619         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5620         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5621         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5622         //PlaneClassify(&frustum[2]);
5623
5624         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5625         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5626         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5627         //PlaneClassify(&frustum[3]);
5628
5629         // nearclip plane
5630         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5631         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5632         //PlaneClassify(&frustum[4]);
5633 }
5634
5635 static void R_View_UpdateWithScissor(const int *myscissor)
5636 {
5637         R_Main_ResizeViewCache();
5638         R_View_SetFrustum(myscissor);
5639         R_View_WorldVisibility(r_refdef.view.useclipplane);
5640         R_View_UpdateEntityVisible();
5641         R_View_UpdateEntityLighting();
5642 }
5643
5644 static void R_View_Update(void)
5645 {
5646         R_Main_ResizeViewCache();
5647         R_View_SetFrustum(NULL);
5648         R_View_WorldVisibility(r_refdef.view.useclipplane);
5649         R_View_UpdateEntityVisible();
5650         R_View_UpdateEntityLighting();
5651 }
5652
5653 float viewscalefpsadjusted = 1.0f;
5654
5655 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5656 {
5657         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5658         scale = bound(0.03125f, scale, 1.0f);
5659         *outwidth = (int)ceil(width * scale);
5660         *outheight = (int)ceil(height * scale);
5661 }
5662
5663 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5664 {
5665         const float *customclipplane = NULL;
5666         float plane[4];
5667         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5668         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5669         {
5670                 // LordHavoc: couldn't figure out how to make this approach the
5671                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5672                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5673                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5674                         dist = r_refdef.view.clipplane.dist;
5675                 plane[0] = r_refdef.view.clipplane.normal[0];
5676                 plane[1] = r_refdef.view.clipplane.normal[1];
5677                 plane[2] = r_refdef.view.clipplane.normal[2];
5678                 plane[3] = -dist;
5679                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5680         }
5681
5682         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5683         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5684
5685         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5686         if (!r_refdef.view.useperspective)
5687                 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);
5688         else if (vid.stencil && r_useinfinitefarclip.integer)
5689                 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);
5690         else
5691                 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);
5692         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5693         R_SetViewport(&r_refdef.view.viewport);
5694         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5695         {
5696                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5697                 float screenplane[4];
5698                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5699                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5700                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5701                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5702                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5703         }
5704 }
5705
5706 void R_EntityMatrix(const matrix4x4_t *matrix)
5707 {
5708         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5709         {
5710                 gl_modelmatrixchanged = false;
5711                 gl_modelmatrix = *matrix;
5712                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5713                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5714                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5715                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5716                 CHECKGLERROR
5717                 switch(vid.renderpath)
5718                 {
5719                 case RENDERPATH_D3D9:
5720 #ifdef SUPPORTD3D
5721                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5722                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5723 #endif
5724                         break;
5725                 case RENDERPATH_D3D10:
5726                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5727                         break;
5728                 case RENDERPATH_D3D11:
5729                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5730                         break;
5731                 case RENDERPATH_GL11:
5732                 case RENDERPATH_GL13:
5733                 case RENDERPATH_GLES1:
5734 #ifndef USE_GLES2
5735                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5736 #endif
5737                         break;
5738                 case RENDERPATH_SOFT:
5739                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5740                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5741                         break;
5742                 case RENDERPATH_GL20:
5743                 case RENDERPATH_GLES2:
5744                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5745                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5746                         break;
5747                 }
5748         }
5749 }
5750
5751 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5752 {
5753         r_viewport_t viewport;
5754
5755         CHECKGLERROR
5756
5757         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5758         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);
5759         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5760         R_SetViewport(&viewport);
5761         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5762         GL_Color(1, 1, 1, 1);
5763         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5764         GL_BlendFunc(GL_ONE, GL_ZERO);
5765         GL_ScissorTest(false);
5766         GL_DepthMask(false);
5767         GL_DepthRange(0, 1);
5768         GL_DepthTest(false);
5769         GL_DepthFunc(GL_LEQUAL);
5770         R_EntityMatrix(&identitymatrix);
5771         R_Mesh_ResetTextureState();
5772         GL_PolygonOffset(0, 0);
5773         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5774         switch(vid.renderpath)
5775         {
5776         case RENDERPATH_GL11:
5777         case RENDERPATH_GL13:
5778         case RENDERPATH_GL20:
5779         case RENDERPATH_GLES1:
5780         case RENDERPATH_GLES2:
5781                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5782                 break;
5783         case RENDERPATH_D3D9:
5784         case RENDERPATH_D3D10:
5785         case RENDERPATH_D3D11:
5786         case RENDERPATH_SOFT:
5787                 break;
5788         }
5789         GL_CullFace(GL_NONE);
5790
5791         CHECKGLERROR
5792 }
5793
5794 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5795 {
5796         DrawQ_Finish();
5797
5798         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5799 }
5800
5801 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5802 {
5803         DrawQ_Finish();
5804
5805         R_SetupView(true, fbo, depthtexture, colortexture);
5806         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5807         GL_Color(1, 1, 1, 1);
5808         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5809         GL_BlendFunc(GL_ONE, GL_ZERO);
5810         GL_ScissorTest(true);
5811         GL_DepthMask(true);
5812         GL_DepthRange(0, 1);
5813         GL_DepthTest(true);
5814         GL_DepthFunc(GL_LEQUAL);
5815         R_EntityMatrix(&identitymatrix);
5816         R_Mesh_ResetTextureState();
5817         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5818         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5819         switch(vid.renderpath)
5820         {
5821         case RENDERPATH_GL11:
5822         case RENDERPATH_GL13:
5823         case RENDERPATH_GL20:
5824         case RENDERPATH_GLES1:
5825         case RENDERPATH_GLES2:
5826                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5827                 break;
5828         case RENDERPATH_D3D9:
5829         case RENDERPATH_D3D10:
5830         case RENDERPATH_D3D11:
5831         case RENDERPATH_SOFT:
5832                 break;
5833         }
5834         GL_CullFace(r_refdef.view.cullface_back);
5835 }
5836
5837 /*
5838 ================
5839 R_RenderView_UpdateViewVectors
5840 ================
5841 */
5842 void R_RenderView_UpdateViewVectors(void)
5843 {
5844         // break apart the view matrix into vectors for various purposes
5845         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5846         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5847         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5848         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5849         // make an inverted copy of the view matrix for tracking sprites
5850         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5851 }
5852
5853 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5854 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5855
5856 static void R_Water_StartFrame(void)
5857 {
5858         int i;
5859         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5860         r_waterstate_waterplane_t *p;
5861         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;
5862
5863         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5864                 return;
5865
5866         switch(vid.renderpath)
5867         {
5868         case RENDERPATH_GL20:
5869         case RENDERPATH_D3D9:
5870         case RENDERPATH_D3D10:
5871         case RENDERPATH_D3D11:
5872         case RENDERPATH_SOFT:
5873         case RENDERPATH_GLES2:
5874                 break;
5875         case RENDERPATH_GL11:
5876         case RENDERPATH_GL13:
5877         case RENDERPATH_GLES1:
5878                 return;
5879         }
5880
5881         // set waterwidth and waterheight to the water resolution that will be
5882         // used (often less than the screen resolution for faster rendering)
5883         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5884
5885         // calculate desired texture sizes
5886         // can't use water if the card does not support the texture size
5887         if (!r_water.integer || r_showsurfaces.integer)
5888                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5889         else if (vid.support.arb_texture_non_power_of_two)
5890         {
5891                 texturewidth = waterwidth;
5892                 textureheight = waterheight;
5893                 camerawidth = waterwidth;
5894                 cameraheight = waterheight;
5895         }
5896         else
5897         {
5898                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5899                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5900                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5901                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5902         }
5903
5904         // allocate textures as needed
5905         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))
5906         {
5907                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5908                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5909                 {
5910                         if (p->texture_refraction)
5911                                 R_FreeTexture(p->texture_refraction);
5912                         p->texture_refraction = NULL;
5913                         if (p->fbo_refraction)
5914                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5915                         p->fbo_refraction = 0;
5916                         if (p->texture_reflection)
5917                                 R_FreeTexture(p->texture_reflection);
5918                         p->texture_reflection = NULL;
5919                         if (p->fbo_reflection)
5920                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5921                         p->fbo_reflection = 0;
5922                         if (p->texture_camera)
5923                                 R_FreeTexture(p->texture_camera);
5924                         p->texture_camera = NULL;
5925                         if (p->fbo_camera)
5926                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5927                         p->fbo_camera = 0;
5928                 }
5929                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5930                 r_fb.water.texturewidth = texturewidth;
5931                 r_fb.water.textureheight = textureheight;
5932                 r_fb.water.camerawidth = camerawidth;
5933                 r_fb.water.cameraheight = cameraheight;
5934         }
5935
5936         if (r_fb.water.texturewidth)
5937         {
5938                 int scaledwidth, scaledheight;
5939
5940                 r_fb.water.enabled = true;
5941
5942                 // water resolution is usually reduced
5943                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5944                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5945                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5946
5947                 // set up variables that will be used in shader setup
5948                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5949                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5950                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5951                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5952         }
5953
5954         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5955         r_fb.water.numwaterplanes = 0;
5956 }
5957
5958 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5959 {
5960         int planeindex, bestplaneindex, vertexindex;
5961         vec3_t mins, maxs, normal, center, v, n;
5962         vec_t planescore, bestplanescore;
5963         mplane_t plane;
5964         r_waterstate_waterplane_t *p;
5965         texture_t *t = R_GetCurrentTexture(surface->texture);
5966
5967         rsurface.texture = t;
5968         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5969         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5970         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5971                 return;
5972         // average the vertex normals, find the surface bounds (after deformvertexes)
5973         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5974         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5975         VectorCopy(n, normal);
5976         VectorCopy(v, mins);
5977         VectorCopy(v, maxs);
5978         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5979         {
5980                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5981                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5982                 VectorAdd(normal, n, normal);
5983                 mins[0] = min(mins[0], v[0]);
5984                 mins[1] = min(mins[1], v[1]);
5985                 mins[2] = min(mins[2], v[2]);
5986                 maxs[0] = max(maxs[0], v[0]);
5987                 maxs[1] = max(maxs[1], v[1]);
5988                 maxs[2] = max(maxs[2], v[2]);
5989         }
5990         VectorNormalize(normal);
5991         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5992
5993         VectorCopy(normal, plane.normal);
5994         VectorNormalize(plane.normal);
5995         plane.dist = DotProduct(center, plane.normal);
5996         PlaneClassify(&plane);
5997         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5998         {
5999                 // skip backfaces (except if nocullface is set)
6000 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6001 //                      return;
6002                 VectorNegate(plane.normal, plane.normal);
6003                 plane.dist *= -1;
6004                 PlaneClassify(&plane);
6005         }
6006
6007
6008         // find a matching plane if there is one
6009         bestplaneindex = -1;
6010         bestplanescore = 1048576.0f;
6011         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6012         {
6013                 if(p->camera_entity == t->camera_entity)
6014                 {
6015                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6016                         if (bestplaneindex < 0 || bestplanescore > planescore)
6017                         {
6018                                 bestplaneindex = planeindex;
6019                                 bestplanescore = planescore;
6020                         }
6021                 }
6022         }
6023         planeindex = bestplaneindex;
6024
6025         // if this surface does not fit any known plane rendered this frame, add one
6026         if (planeindex < 0 || bestplanescore > 0.001f)
6027         {
6028                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6029                 {
6030                         // store the new plane
6031                         planeindex = r_fb.water.numwaterplanes++;
6032                         p = r_fb.water.waterplanes + planeindex;
6033                         p->plane = plane;
6034                         // clear materialflags and pvs
6035                         p->materialflags = 0;
6036                         p->pvsvalid = false;
6037                         p->camera_entity = t->camera_entity;
6038                         VectorCopy(mins, p->mins);
6039                         VectorCopy(maxs, p->maxs);
6040                 }
6041                 else
6042                 {
6043                         // We're totally screwed.
6044                         return;
6045                 }
6046         }
6047         else
6048         {
6049                 // merge mins/maxs when we're adding this surface to the plane
6050                 p = r_fb.water.waterplanes + planeindex;
6051                 p->mins[0] = min(p->mins[0], mins[0]);
6052                 p->mins[1] = min(p->mins[1], mins[1]);
6053                 p->mins[2] = min(p->mins[2], mins[2]);
6054                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6055                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6056                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6057         }
6058         // merge this surface's materialflags into the waterplane
6059         p->materialflags |= t->currentmaterialflags;
6060         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6061         {
6062                 // merge this surface's PVS into the waterplane
6063                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6064                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6065                 {
6066                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6067                         p->pvsvalid = true;
6068                 }
6069         }
6070 }
6071
6072 extern cvar_t r_drawparticles;
6073 extern cvar_t r_drawdecals;
6074
6075 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6076 {
6077         int myscissor[4];
6078         r_refdef_view_t originalview;
6079         r_refdef_view_t myview;
6080         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;
6081         r_waterstate_waterplane_t *p;
6082         vec3_t visorigin;
6083         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;
6084         char vabuf[1024];
6085
6086         originalview = r_refdef.view;
6087
6088         // lowquality hack, temporarily shut down some cvars and restore afterwards
6089         qualityreduction = r_water_lowquality.integer;
6090         if (qualityreduction > 0)
6091         {
6092                 if (qualityreduction >= 1)
6093                 {
6094                         old_r_shadows = r_shadows.integer;
6095                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6096                         old_r_dlight = r_shadow_realtime_dlight.integer;
6097                         Cvar_SetValueQuick(&r_shadows, 0);
6098                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6099                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6100                 }
6101                 if (qualityreduction >= 2)
6102                 {
6103                         old_r_dynamic = r_dynamic.integer;
6104                         old_r_particles = r_drawparticles.integer;
6105                         old_r_decals = r_drawdecals.integer;
6106                         Cvar_SetValueQuick(&r_dynamic, 0);
6107                         Cvar_SetValueQuick(&r_drawparticles, 0);
6108                         Cvar_SetValueQuick(&r_drawdecals, 0);
6109                 }
6110         }
6111
6112         // make sure enough textures are allocated
6113         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6114         {
6115                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6116                         continue;
6117                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6118                 {
6119                         if (!p->texture_refraction)
6120                                 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);
6121                         if (!p->texture_refraction)
6122                                 goto error;
6123                         if (usewaterfbo)
6124                         {
6125                                 if (r_fb.water.depthtexture == NULL)
6126                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6127                                 if (p->fbo_refraction == 0)
6128                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6129                         }
6130                 }
6131                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6132                 {
6133                         if (!p->texture_camera)
6134                                 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);
6135                         if (!p->texture_camera)
6136                                 goto error;
6137                         if (usewaterfbo)
6138                         {
6139                                 if (r_fb.water.depthtexture == NULL)
6140                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6141                                 if (p->fbo_camera == 0)
6142                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6143                         }
6144                 }
6145
6146                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6147                 {
6148                         if (!p->texture_reflection)
6149                                 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);
6150                         if (!p->texture_reflection)
6151                                 goto error;
6152                         if (usewaterfbo)
6153                         {
6154                                 if (r_fb.water.depthtexture == NULL)
6155                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6156                                 if (p->fbo_reflection == 0)
6157                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6158                         }
6159                 }
6160         }
6161
6162         // render views
6163         r_refdef.view = originalview;
6164         r_refdef.view.showdebug = false;
6165         r_refdef.view.width = r_fb.water.waterwidth;
6166         r_refdef.view.height = r_fb.water.waterheight;
6167         r_refdef.view.useclipplane = true;
6168         myview = r_refdef.view;
6169         r_fb.water.renderingscene = true;
6170         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6171         {
6172                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6173                         continue;
6174                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6175                 {
6176                         r_refdef.view = myview;
6177                         if(r_water_scissormode.integer)
6178                         {
6179                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6180                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6181                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6182                         }
6183
6184                         // render reflected scene and copy into texture
6185                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6186                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6187                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6188                         r_refdef.view.clipplane = p->plane;
6189                         // reverse the cullface settings for this render
6190                         r_refdef.view.cullface_front = GL_FRONT;
6191                         r_refdef.view.cullface_back = GL_BACK;
6192                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6193                         {
6194                                 r_refdef.view.usecustompvs = true;
6195                                 if (p->pvsvalid)
6196                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6197                                 else
6198                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6199                         }
6200
6201                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6202                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6203                         R_ClearScreen(r_refdef.fogenabled);
6204                         if(r_water_scissormode.integer & 2)
6205                                 R_View_UpdateWithScissor(myscissor);
6206                         else
6207                                 R_View_Update();
6208                         R_AnimCache_CacheVisibleEntities();
6209                         if(r_water_scissormode.integer & 1)
6210                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6211                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6212
6213                         if (!p->fbo_reflection)
6214                                 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);
6215                         r_fb.water.hideplayer = false;
6216                 }
6217
6218                 // render the normal view scene and copy into texture
6219                 // (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)
6220                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6221                 {
6222                         r_refdef.view = myview;
6223                         if(r_water_scissormode.integer)
6224                         {
6225                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6226                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6227                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6228                         }
6229
6230                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6231
6232                         r_refdef.view.clipplane = p->plane;
6233                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6234                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6235
6236                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6237                         {
6238                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6239                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6240                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6241                                 R_RenderView_UpdateViewVectors();
6242                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6243                                 {
6244                                         r_refdef.view.usecustompvs = true;
6245                                         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);
6246                                 }
6247                         }
6248
6249                         PlaneClassify(&r_refdef.view.clipplane);
6250
6251                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6252                         R_ClearScreen(r_refdef.fogenabled);
6253                         if(r_water_scissormode.integer & 2)
6254                                 R_View_UpdateWithScissor(myscissor);
6255                         else
6256                                 R_View_Update();
6257                         R_AnimCache_CacheVisibleEntities();
6258                         if(r_water_scissormode.integer & 1)
6259                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6260                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6261
6262                         if (!p->fbo_refraction)
6263                                 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);
6264                         r_fb.water.hideplayer = false;
6265                 }
6266                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6267                 {
6268                         r_refdef.view = myview;
6269
6270                         r_refdef.view.clipplane = p->plane;
6271                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6272                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6273
6274                         r_refdef.view.width = r_fb.water.camerawidth;
6275                         r_refdef.view.height = r_fb.water.cameraheight;
6276                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6277                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6278                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6279                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6280
6281                         if(p->camera_entity)
6282                         {
6283                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6284                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6285                         }
6286
6287                         // note: all of the view is used for displaying... so
6288                         // there is no use in scissoring
6289
6290                         // reverse the cullface settings for this render
6291                         r_refdef.view.cullface_front = GL_FRONT;
6292                         r_refdef.view.cullface_back = GL_BACK;
6293                         // also reverse the view matrix
6294                         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
6295                         R_RenderView_UpdateViewVectors();
6296                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6297                         {
6298                                 r_refdef.view.usecustompvs = true;
6299                                 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);
6300                         }
6301                         
6302                         // camera needs no clipplane
6303                         r_refdef.view.useclipplane = false;
6304
6305                         PlaneClassify(&r_refdef.view.clipplane);
6306
6307                         r_fb.water.hideplayer = false;
6308
6309                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6310                         R_ClearScreen(r_refdef.fogenabled);
6311                         R_View_Update();
6312                         R_AnimCache_CacheVisibleEntities();
6313                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6314
6315                         if (!p->fbo_camera)
6316                                 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);
6317                         r_fb.water.hideplayer = false;
6318                 }
6319
6320         }
6321         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6322         r_fb.water.renderingscene = false;
6323         r_refdef.view = originalview;
6324         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6325         if (!r_fb.water.depthtexture)
6326                 R_ClearScreen(r_refdef.fogenabled);
6327         R_View_Update();
6328         R_AnimCache_CacheVisibleEntities();
6329         goto finish;
6330 error:
6331         r_refdef.view = originalview;
6332         r_fb.water.renderingscene = false;
6333         Cvar_SetValueQuick(&r_water, 0);
6334         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6335 finish:
6336         // lowquality hack, restore cvars
6337         if (qualityreduction > 0)
6338         {
6339                 if (qualityreduction >= 1)
6340                 {
6341                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6342                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6343                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6344                 }
6345                 if (qualityreduction >= 2)
6346                 {
6347                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6348                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6349                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6350                 }
6351         }
6352 }
6353
6354 static void R_Bloom_StartFrame(void)
6355 {
6356         int i;
6357         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6358         int viewwidth, viewheight;
6359         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6360         textype_t textype = TEXTYPE_COLORBUFFER;
6361
6362         switch (vid.renderpath)
6363         {
6364         case RENDERPATH_GL20:
6365                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6366                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6367                 {
6368                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6369                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6370                 }
6371                 break;
6372         case RENDERPATH_GL11:
6373         case RENDERPATH_GL13:
6374         case RENDERPATH_GLES1:
6375         case RENDERPATH_GLES2:
6376         case RENDERPATH_D3D9:
6377         case RENDERPATH_D3D10:
6378         case RENDERPATH_D3D11:
6379                 r_fb.usedepthtextures = false;
6380                 break;
6381         case RENDERPATH_SOFT:
6382                 r_fb.usedepthtextures = true;
6383                 break;
6384         }
6385
6386         if (r_viewscale_fpsscaling.integer)
6387         {
6388                 double actualframetime;
6389                 double targetframetime;
6390                 double adjust;
6391                 actualframetime = r_refdef.lastdrawscreentime;
6392                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6393                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6394                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6395                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6396                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6397                 viewscalefpsadjusted += adjust;
6398                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6399         }
6400         else
6401                 viewscalefpsadjusted = 1.0f;
6402
6403         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6404
6405         switch(vid.renderpath)
6406         {
6407         case RENDERPATH_GL20:
6408         case RENDERPATH_D3D9:
6409         case RENDERPATH_D3D10:
6410         case RENDERPATH_D3D11:
6411         case RENDERPATH_SOFT:
6412         case RENDERPATH_GLES2:
6413                 break;
6414         case RENDERPATH_GL11:
6415         case RENDERPATH_GL13:
6416         case RENDERPATH_GLES1:
6417                 return;
6418         }
6419
6420         // set bloomwidth and bloomheight to the bloom resolution that will be
6421         // used (often less than the screen resolution for faster rendering)
6422         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6423         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6424         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6425         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6426         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6427
6428         // calculate desired texture sizes
6429         if (vid.support.arb_texture_non_power_of_two)
6430         {
6431                 screentexturewidth = vid.width;
6432                 screentextureheight = vid.height;
6433                 bloomtexturewidth = r_fb.bloomwidth;
6434                 bloomtextureheight = r_fb.bloomheight;
6435         }
6436         else
6437         {
6438                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6439                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6440                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6441                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6442         }
6443
6444         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))
6445         {
6446                 Cvar_SetValueQuick(&r_bloom, 0);
6447                 Cvar_SetValueQuick(&r_motionblur, 0);
6448                 Cvar_SetValueQuick(&r_damageblur, 0);
6449         }
6450
6451         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6452          && !r_bloom.integer
6453          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6454          && !useviewfbo
6455          && r_viewscale.value == 1.0f
6456          && !r_viewscale_fpsscaling.integer)
6457                 screentexturewidth = screentextureheight = 0;
6458         if (!r_bloom.integer)
6459                 bloomtexturewidth = bloomtextureheight = 0;
6460
6461         // allocate textures as needed
6462         if (r_fb.screentexturewidth != screentexturewidth
6463          || r_fb.screentextureheight != screentextureheight
6464          || r_fb.bloomtexturewidth != bloomtexturewidth
6465          || r_fb.bloomtextureheight != bloomtextureheight
6466          || r_fb.textype != textype
6467          || useviewfbo != (r_fb.fbo != 0))
6468         {
6469                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6470                 {
6471                         if (r_fb.bloomtexture[i])
6472                                 R_FreeTexture(r_fb.bloomtexture[i]);
6473                         r_fb.bloomtexture[i] = NULL;
6474
6475                         if (r_fb.bloomfbo[i])
6476                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6477                         r_fb.bloomfbo[i] = 0;
6478                 }
6479
6480                 if (r_fb.fbo)
6481                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6482                 r_fb.fbo = 0;
6483
6484                 if (r_fb.colortexture)
6485                         R_FreeTexture(r_fb.colortexture);
6486                 r_fb.colortexture = NULL;
6487
6488                 if (r_fb.depthtexture)
6489                         R_FreeTexture(r_fb.depthtexture);
6490                 r_fb.depthtexture = NULL;
6491
6492                 if (r_fb.ghosttexture)
6493                         R_FreeTexture(r_fb.ghosttexture);
6494                 r_fb.ghosttexture = NULL;
6495
6496                 r_fb.screentexturewidth = screentexturewidth;
6497                 r_fb.screentextureheight = screentextureheight;
6498                 r_fb.bloomtexturewidth = bloomtexturewidth;
6499                 r_fb.bloomtextureheight = bloomtextureheight;
6500                 r_fb.textype = textype;
6501
6502                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6503                 {
6504                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6505                                 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);
6506                         r_fb.ghosttexture_valid = false;
6507                         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);
6508                         if (useviewfbo)
6509                         {
6510                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6511                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6512                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6513                         }
6514                 }
6515
6516                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6517                 {
6518                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6519                         {
6520                                 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);
6521                                 if (useviewfbo)
6522                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6523                         }
6524                 }
6525         }
6526
6527         // bloom texture is a different resolution
6528         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6529         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6530         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6531         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6532         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6533
6534         // set up a texcoord array for the full resolution screen image
6535         // (we have to keep this around to copy back during final render)
6536         r_fb.screentexcoord2f[0] = 0;
6537         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6538         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6539         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6540         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6541         r_fb.screentexcoord2f[5] = 0;
6542         r_fb.screentexcoord2f[6] = 0;
6543         r_fb.screentexcoord2f[7] = 0;
6544
6545         if(r_fb.fbo) 
6546         {
6547                 for (i = 1;i < 8;i += 2)
6548                 {
6549                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6550                 }
6551         }
6552
6553         // set up a texcoord array for the reduced resolution bloom image
6554         // (which will be additive blended over the screen image)
6555         r_fb.bloomtexcoord2f[0] = 0;
6556         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6557         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6558         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6559         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6560         r_fb.bloomtexcoord2f[5] = 0;
6561         r_fb.bloomtexcoord2f[6] = 0;
6562         r_fb.bloomtexcoord2f[7] = 0;
6563
6564         switch(vid.renderpath)
6565         {
6566         case RENDERPATH_GL11:
6567         case RENDERPATH_GL13:
6568         case RENDERPATH_GL20:
6569         case RENDERPATH_SOFT:
6570         case RENDERPATH_GLES1:
6571         case RENDERPATH_GLES2:
6572                 break;
6573         case RENDERPATH_D3D9:
6574         case RENDERPATH_D3D10:
6575         case RENDERPATH_D3D11:
6576                 for (i = 0;i < 4;i++)
6577                 {
6578                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6579                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6580                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6581                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6582                 }
6583                 break;
6584         }
6585
6586         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6587
6588         if (r_fb.fbo)
6589                 r_refdef.view.clear = true;
6590 }
6591
6592 static void R_Bloom_MakeTexture(void)
6593 {
6594         int x, range, dir;
6595         float xoffset, yoffset, r, brighten;
6596         rtexture_t *intex;
6597         float colorscale = r_bloom_colorscale.value;
6598
6599         r_refdef.stats[r_stat_bloom]++;
6600     
6601 #if 0
6602     // this copy is unnecessary since it happens in R_BlendView already
6603         if (!r_fb.fbo)
6604         {
6605                 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);
6606                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6607         }
6608 #endif
6609
6610         // scale down screen texture to the bloom texture size
6611         CHECKGLERROR
6612         r_fb.bloomindex = 0;
6613         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6614         R_SetViewport(&r_fb.bloomviewport);
6615         GL_DepthTest(false);
6616         GL_BlendFunc(GL_ONE, GL_ZERO);
6617         GL_Color(colorscale, colorscale, colorscale, 1);
6618         // 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...
6619         switch(vid.renderpath)
6620         {
6621         case RENDERPATH_GL11:
6622         case RENDERPATH_GL13:
6623         case RENDERPATH_GL20:
6624         case RENDERPATH_GLES1:
6625         case RENDERPATH_GLES2:
6626         case RENDERPATH_SOFT:
6627                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6628                 break;
6629         case RENDERPATH_D3D9:
6630         case RENDERPATH_D3D10:
6631         case RENDERPATH_D3D11:
6632                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6633                 break;
6634         }
6635         // TODO: do boxfilter scale-down in shader?
6636         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6637         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6638         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6639
6640         // we now have a properly scaled bloom image
6641         if (!r_fb.bloomfbo[r_fb.bloomindex])
6642         {
6643                 // copy it into the bloom texture
6644                 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);
6645                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6646         }
6647
6648         // multiply bloom image by itself as many times as desired
6649         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6650         {
6651                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6652                 r_fb.bloomindex ^= 1;
6653                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6654                 x *= 2;
6655                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6656                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6657                 {
6658                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6659                         GL_Color(r,r,r,1); // apply fix factor
6660                 }
6661                 else
6662                 {
6663                         if(x <= 2)
6664                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6665                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6666                         GL_Color(1,1,1,1); // no fix factor supported here
6667                 }
6668                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6669                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6670                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6671                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6672
6673                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6674                 {
6675                         // copy the darkened image to a texture
6676                         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);
6677                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6678                 }
6679         }
6680
6681         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6682         brighten = r_bloom_brighten.value;
6683         brighten = sqrt(brighten);
6684         if(range >= 1)
6685                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6686
6687         for (dir = 0;dir < 2;dir++)
6688         {
6689                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6690                 r_fb.bloomindex ^= 1;
6691                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6692                 // blend on at multiple vertical offsets to achieve a vertical blur
6693                 // TODO: do offset blends using GLSL
6694                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6695                 GL_BlendFunc(GL_ONE, GL_ZERO);
6696                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6697                 for (x = -range;x <= range;x++)
6698                 {
6699                         if (!dir){xoffset = 0;yoffset = x;}
6700                         else {xoffset = x;yoffset = 0;}
6701                         xoffset /= (float)r_fb.bloomtexturewidth;
6702                         yoffset /= (float)r_fb.bloomtextureheight;
6703                         // compute a texcoord array with the specified x and y offset
6704                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6705                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6706                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6707                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6708                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6709                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6710                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6711                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6712                         // this r value looks like a 'dot' particle, fading sharply to
6713                         // black at the edges
6714                         // (probably not realistic but looks good enough)
6715                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6716                         //r = brighten/(range*2+1);
6717                         r = brighten / (range * 2 + 1);
6718                         if(range >= 1)
6719                                 r *= (1 - x*x/(float)(range*range));
6720                         GL_Color(r, r, r, 1);
6721                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6722                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6723                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6724                         GL_BlendFunc(GL_ONE, GL_ONE);
6725                 }
6726
6727                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6728                 {
6729                         // copy the vertically or horizontally blurred bloom view to a texture
6730                         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);
6731                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6732                 }
6733         }
6734 }
6735
6736 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6737 {
6738         unsigned int permutation;
6739         float uservecs[4][4];
6740
6741         R_EntityMatrix(&identitymatrix);
6742
6743         switch (vid.renderpath)
6744         {
6745         case RENDERPATH_GL20:
6746         case RENDERPATH_D3D9:
6747         case RENDERPATH_D3D10:
6748         case RENDERPATH_D3D11:
6749         case RENDERPATH_SOFT:
6750         case RENDERPATH_GLES2:
6751                 permutation =
6752                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6753                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6754                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6755                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6756                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6757
6758                 if (r_fb.colortexture)
6759                 {
6760                         if (!r_fb.fbo)
6761                         {
6762                                 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);
6763                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6764                         }
6765
6766                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6767                         {
6768                                 // declare variables
6769                                 float blur_factor, blur_mouseaccel, blur_velocity;
6770                                 static float blur_average; 
6771                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6772
6773                                 // set a goal for the factoring
6774                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6775                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6776                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6777                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6778                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6779                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6780
6781                                 // from the goal, pick an averaged value between goal and last value
6782                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6783                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6784
6785                                 // enforce minimum amount of blur 
6786                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6787
6788                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6789
6790                                 // calculate values into a standard alpha
6791                                 cl.motionbluralpha = 1 - exp(-
6792                                                 (
6793                                                  (r_motionblur.value * blur_factor / 80)
6794                                                  +
6795                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6796                                                 )
6797                                                 /
6798                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6799                                           );
6800
6801                                 // randomization for the blur value to combat persistent ghosting
6802                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6803                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6804
6805                                 // apply the blur
6806                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6807                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6808                                 {
6809                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6810                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6811                                         switch(vid.renderpath)
6812                                         {
6813                                         case RENDERPATH_GL11:
6814                                         case RENDERPATH_GL13:
6815                                         case RENDERPATH_GL20:
6816                                         case RENDERPATH_GLES1:
6817                                         case RENDERPATH_GLES2:
6818                                         case RENDERPATH_SOFT:
6819                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6820                                                 break;
6821                                         case RENDERPATH_D3D9:
6822                                         case RENDERPATH_D3D10:
6823                                         case RENDERPATH_D3D11:
6824                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6825                                                 break;
6826                                         }
6827                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6828                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6829                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6830                                 }
6831
6832                                 // updates old view angles for next pass
6833                                 VectorCopy(cl.viewangles, blur_oldangles);
6834
6835                                 // copy view into the ghost texture
6836                                 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);
6837                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6838                                 r_fb.ghosttexture_valid = true;
6839                         }
6840                 }
6841                 else
6842                 {
6843                         // no r_fb.colortexture means we're rendering to the real fb
6844                         // we may still have to do view tint...
6845                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6846                         {
6847                                 // apply a color tint to the whole view
6848                                 R_ResetViewRendering2D(0, NULL, NULL);
6849                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6850                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6851                                 R_SetupShader_Generic_NoTexture(false, true);
6852                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6853                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854                         }
6855                         break; // no screen processing, no bloom, skip it
6856                 }
6857
6858                 if (r_fb.bloomtexture[0])
6859                 {
6860                         // make the bloom texture
6861                         R_Bloom_MakeTexture();
6862                 }
6863
6864 #if _MSC_VER >= 1400
6865 #define sscanf sscanf_s
6866 #endif
6867                 memset(uservecs, 0, sizeof(uservecs));
6868                 if (r_glsl_postprocess_uservec1_enable.integer)
6869                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6870                 if (r_glsl_postprocess_uservec2_enable.integer)
6871                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6872                 if (r_glsl_postprocess_uservec3_enable.integer)
6873                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6874                 if (r_glsl_postprocess_uservec4_enable.integer)
6875                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6876
6877                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6878                 GL_Color(1, 1, 1, 1);
6879                 GL_BlendFunc(GL_ONE, GL_ZERO);
6880
6881                 switch(vid.renderpath)
6882                 {
6883                 case RENDERPATH_GL20:
6884                 case RENDERPATH_GLES2:
6885                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6886                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6887                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6888                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6889                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6890                         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]);
6891                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6892                         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]);
6893                         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]);
6894                         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]);
6895                         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]);
6896                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6897                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6898                         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);
6899                         break;
6900                 case RENDERPATH_D3D9:
6901 #ifdef SUPPORTD3D
6902                         // 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...
6903                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6904                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6905                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6906                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6907                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6908                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6909                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6910                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6911                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6912                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6913                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6914                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6915                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6916                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6917 #endif
6918                         break;
6919                 case RENDERPATH_D3D10:
6920                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6921                         break;
6922                 case RENDERPATH_D3D11:
6923                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6924                         break;
6925                 case RENDERPATH_SOFT:
6926                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6927                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6928                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6929                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6930                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6931                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6932                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6933                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6934                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6935                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6936                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6937                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6938                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6939                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6940                         break;
6941                 default:
6942                         break;
6943                 }
6944                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6945                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6946                 break;
6947         case RENDERPATH_GL11:
6948         case RENDERPATH_GL13:
6949         case RENDERPATH_GLES1:
6950                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6951                 {
6952                         // apply a color tint to the whole view
6953                         R_ResetViewRendering2D(0, NULL, NULL);
6954                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6955                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6956                         R_SetupShader_Generic_NoTexture(false, true);
6957                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6958                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6959                 }
6960                 break;
6961         }
6962 }
6963
6964 matrix4x4_t r_waterscrollmatrix;
6965
6966 void R_UpdateFog(void)
6967 {
6968         // Nehahra fog
6969         if (gamemode == GAME_NEHAHRA)
6970         {
6971                 if (gl_fogenable.integer)
6972                 {
6973                         r_refdef.oldgl_fogenable = true;
6974                         r_refdef.fog_density = gl_fogdensity.value;
6975                         r_refdef.fog_red = gl_fogred.value;
6976                         r_refdef.fog_green = gl_foggreen.value;
6977                         r_refdef.fog_blue = gl_fogblue.value;
6978                         r_refdef.fog_alpha = 1;
6979                         r_refdef.fog_start = 0;
6980                         r_refdef.fog_end = gl_skyclip.value;
6981                         r_refdef.fog_height = 1<<30;
6982                         r_refdef.fog_fadedepth = 128;
6983                 }
6984                 else if (r_refdef.oldgl_fogenable)
6985                 {
6986                         r_refdef.oldgl_fogenable = false;
6987                         r_refdef.fog_density = 0;
6988                         r_refdef.fog_red = 0;
6989                         r_refdef.fog_green = 0;
6990                         r_refdef.fog_blue = 0;
6991                         r_refdef.fog_alpha = 0;
6992                         r_refdef.fog_start = 0;
6993                         r_refdef.fog_end = 0;
6994                         r_refdef.fog_height = 1<<30;
6995                         r_refdef.fog_fadedepth = 128;
6996                 }
6997         }
6998
6999         // fog parms
7000         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7001         r_refdef.fog_start = max(0, r_refdef.fog_start);
7002         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7003
7004         if (r_refdef.fog_density && r_drawfog.integer)
7005         {
7006                 r_refdef.fogenabled = true;
7007                 // this is the point where the fog reaches 0.9986 alpha, which we
7008                 // consider a good enough cutoff point for the texture
7009                 // (0.9986 * 256 == 255.6)
7010                 if (r_fog_exp2.integer)
7011                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7012                 else
7013                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7014                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7015                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7016                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7017                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7018                         R_BuildFogHeightTexture();
7019                 // fog color was already set
7020                 // update the fog texture
7021                 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)
7022                         R_BuildFogTexture();
7023                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7024                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7025         }
7026         else
7027                 r_refdef.fogenabled = false;
7028
7029         // fog color
7030         if (r_refdef.fog_density)
7031         {
7032                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7033                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7034                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7035
7036                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7037                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7038                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7039                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7040
7041                 {
7042                         vec3_t fogvec;
7043                         VectorCopy(r_refdef.fogcolor, fogvec);
7044                         //   color.rgb *= ContrastBoost * SceneBrightness;
7045                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7046                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7047                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7048                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7049                 }
7050         }
7051 }
7052
7053 void R_UpdateVariables(void)
7054 {
7055         R_Textures_Frame();
7056
7057         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7058
7059         r_refdef.farclip = r_farclip_base.value;
7060         if (r_refdef.scene.worldmodel)
7061                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7062         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7063
7064         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7065                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7066         r_refdef.polygonfactor = 0;
7067         r_refdef.polygonoffset = 0;
7068         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7069         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7070
7071         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7072         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7073         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7074         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7075         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7076         if (FAKELIGHT_ENABLED)
7077         {
7078                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7079         }
7080         else if (r_refdef.scene.worldmodel)
7081         {
7082                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7083         }
7084         if (r_showsurfaces.integer)
7085         {
7086                 r_refdef.scene.rtworld = false;
7087                 r_refdef.scene.rtworldshadows = false;
7088                 r_refdef.scene.rtdlight = false;
7089                 r_refdef.scene.rtdlightshadows = false;
7090                 r_refdef.lightmapintensity = 0;
7091         }
7092
7093         r_gpuskeletal = false;
7094         switch(vid.renderpath)
7095         {
7096         case RENDERPATH_GL20:
7097                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7098         case RENDERPATH_D3D9:
7099         case RENDERPATH_D3D10:
7100         case RENDERPATH_D3D11:
7101         case RENDERPATH_SOFT:
7102         case RENDERPATH_GLES2:
7103                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7104                 {
7105                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7106                         {
7107                                 // build GLSL gamma texture
7108 #define RAMPWIDTH 256
7109                                 unsigned short ramp[RAMPWIDTH * 3];
7110                                 unsigned char rampbgr[RAMPWIDTH][4];
7111                                 int i;
7112
7113                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7114
7115                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7116                                 for(i = 0; i < RAMPWIDTH; ++i)
7117                                 {
7118                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7119                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7120                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7121                                         rampbgr[i][3] = 0;
7122                                 }
7123                                 if (r_texture_gammaramps)
7124                                 {
7125                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7126                                 }
7127                                 else
7128                                 {
7129                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7130                                 }
7131                         }
7132                 }
7133                 else
7134                 {
7135                         // remove GLSL gamma texture
7136                 }
7137                 break;
7138         case RENDERPATH_GL11:
7139         case RENDERPATH_GL13:
7140         case RENDERPATH_GLES1:
7141                 break;
7142         }
7143 }
7144
7145 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7146 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7147 /*
7148 ================
7149 R_SelectScene
7150 ================
7151 */
7152 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7153         if( scenetype != r_currentscenetype ) {
7154                 // store the old scenetype
7155                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7156                 r_currentscenetype = scenetype;
7157                 // move in the new scene
7158                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7159         }
7160 }
7161
7162 /*
7163 ================
7164 R_GetScenePointer
7165 ================
7166 */
7167 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7168 {
7169         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7170         if( scenetype == r_currentscenetype ) {
7171                 return &r_refdef.scene;
7172         } else {
7173                 return &r_scenes_store[ scenetype ];
7174         }
7175 }
7176
7177 static int R_SortEntities_Compare(const void *ap, const void *bp)
7178 {
7179         const entity_render_t *a = *(const entity_render_t **)ap;
7180         const entity_render_t *b = *(const entity_render_t **)bp;
7181
7182         // 1. compare model
7183         if(a->model < b->model)
7184                 return -1;
7185         if(a->model > b->model)
7186                 return +1;
7187
7188         // 2. compare skin
7189         // TODO possibly calculate the REAL skinnum here first using
7190         // skinscenes?
7191         if(a->skinnum < b->skinnum)
7192                 return -1;
7193         if(a->skinnum > b->skinnum)
7194                 return +1;
7195
7196         // everything we compared is equal
7197         return 0;
7198 }
7199 static void R_SortEntities(void)
7200 {
7201         // below or equal 2 ents, sorting never gains anything
7202         if(r_refdef.scene.numentities <= 2)
7203                 return;
7204         // sort
7205         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7206 }
7207
7208 /*
7209 ================
7210 R_RenderView
7211 ================
7212 */
7213 int dpsoftrast_test;
7214 extern cvar_t r_shadow_bouncegrid;
7215 void R_RenderView(void)
7216 {
7217         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7218         int fbo;
7219         rtexture_t *depthtexture;
7220         rtexture_t *colortexture;
7221
7222         dpsoftrast_test = r_test.integer;
7223
7224         if (r_timereport_active)
7225                 R_TimeReport("start");
7226         r_textureframe++; // used only by R_GetCurrentTexture
7227         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7228
7229         if(R_CompileShader_CheckStaticParms())
7230                 R_GLSL_Restart_f();
7231
7232         if (!r_drawentities.integer)
7233                 r_refdef.scene.numentities = 0;
7234         else if (r_sortentities.integer)
7235                 R_SortEntities();
7236
7237         R_AnimCache_ClearCache();
7238
7239         /* adjust for stereo display */
7240         if(R_Stereo_Active())
7241         {
7242                 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);
7243                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7244         }
7245
7246         if (r_refdef.view.isoverlay)
7247         {
7248                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7249                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7250                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7251                 R_TimeReport("depthclear");
7252
7253                 r_refdef.view.showdebug = false;
7254
7255                 r_fb.water.enabled = false;
7256                 r_fb.water.numwaterplanes = 0;
7257
7258                 R_RenderScene(0, NULL, NULL);
7259
7260                 r_refdef.view.matrix = originalmatrix;
7261
7262                 CHECKGLERROR
7263                 return;
7264         }
7265
7266         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7267         {
7268                 r_refdef.view.matrix = originalmatrix;
7269                 return;
7270         }
7271
7272         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7273
7274         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7275                 // in sRGB fallback, behave similar to true sRGB: convert this
7276                 // value from linear to sRGB
7277                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7278
7279         R_RenderView_UpdateViewVectors();
7280
7281         R_Shadow_UpdateWorldLightSelection();
7282
7283         R_Bloom_StartFrame();
7284
7285         // apply bloom brightness offset
7286         if(r_fb.bloomtexture[0])
7287                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7288
7289         R_Water_StartFrame();
7290
7291         // now we probably have an fbo to render into
7292         fbo = r_fb.fbo;
7293         depthtexture = r_fb.depthtexture;
7294         colortexture = r_fb.colortexture;
7295
7296         CHECKGLERROR
7297         if (r_timereport_active)
7298                 R_TimeReport("viewsetup");
7299
7300         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7301
7302         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7303         {
7304                 R_ClearScreen(r_refdef.fogenabled);
7305                 if (r_timereport_active)
7306                         R_TimeReport("viewclear");
7307         }
7308         r_refdef.view.clear = true;
7309
7310         r_refdef.view.showdebug = true;
7311
7312         R_View_Update();
7313         if (r_timereport_active)
7314                 R_TimeReport("visibility");
7315
7316         R_AnimCache_CacheVisibleEntities();
7317         if (r_timereport_active)
7318                 R_TimeReport("animcache");
7319
7320         R_Shadow_UpdateBounceGridTexture();
7321         if (r_timereport_active && r_shadow_bouncegrid.integer)
7322                 R_TimeReport("bouncegrid");
7323
7324         r_fb.water.numwaterplanes = 0;
7325         if (r_fb.water.enabled)
7326                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7327
7328         R_RenderScene(fbo, depthtexture, colortexture);
7329         r_fb.water.numwaterplanes = 0;
7330
7331         R_BlendView(fbo, depthtexture, colortexture);
7332         if (r_timereport_active)
7333                 R_TimeReport("blendview");
7334
7335         GL_Scissor(0, 0, vid.width, vid.height);
7336         GL_ScissorTest(false);
7337
7338         r_refdef.view.matrix = originalmatrix;
7339
7340         CHECKGLERROR
7341 }
7342
7343 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7344 {
7345         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7346         {
7347                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7348                 if (r_timereport_active)
7349                         R_TimeReport("waterworld");
7350         }
7351
7352         // don't let sound skip if going slow
7353         if (r_refdef.scene.extraupdate)
7354                 S_ExtraUpdate ();
7355
7356         R_DrawModelsAddWaterPlanes();
7357         if (r_timereport_active)
7358                 R_TimeReport("watermodels");
7359
7360         if (r_fb.water.numwaterplanes)
7361         {
7362                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7363                 if (r_timereport_active)
7364                         R_TimeReport("waterscenes");
7365         }
7366 }
7367
7368 extern cvar_t cl_locs_show;
7369 static void R_DrawLocs(void);
7370 static void R_DrawEntityBBoxes(void);
7371 static void R_DrawModelDecals(void);
7372 extern cvar_t cl_decals_newsystem;
7373 extern qboolean r_shadow_usingdeferredprepass;
7374 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7375 {
7376         qboolean shadowmapping = false;
7377
7378         if (r_timereport_active)
7379                 R_TimeReport("beginscene");
7380
7381         r_refdef.stats[r_stat_renders]++;
7382
7383         R_UpdateFog();
7384
7385         // don't let sound skip if going slow
7386         if (r_refdef.scene.extraupdate)
7387                 S_ExtraUpdate ();
7388
7389         R_MeshQueue_BeginScene();
7390
7391         R_SkyStartFrame();
7392
7393         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);
7394
7395         if (r_timereport_active)
7396                 R_TimeReport("skystartframe");
7397
7398         if (cl.csqc_vidvars.drawworld)
7399         {
7400                 // don't let sound skip if going slow
7401                 if (r_refdef.scene.extraupdate)
7402                         S_ExtraUpdate ();
7403
7404                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7405                 {
7406                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7407                         if (r_timereport_active)
7408                                 R_TimeReport("worldsky");
7409                 }
7410
7411                 if (R_DrawBrushModelsSky() && r_timereport_active)
7412                         R_TimeReport("bmodelsky");
7413
7414                 if (skyrendermasked && skyrenderlater)
7415                 {
7416                         // we have to force off the water clipping plane while rendering sky
7417                         R_SetupView(false, fbo, depthtexture, colortexture);
7418                         R_Sky();
7419                         R_SetupView(true, fbo, depthtexture, colortexture);
7420                         if (r_timereport_active)
7421                                 R_TimeReport("sky");
7422                 }
7423         }
7424
7425         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7426         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7427                 R_Shadow_PrepareModelShadows();
7428         if (r_timereport_active)
7429                 R_TimeReport("preparelights");
7430
7431         if (R_Shadow_ShadowMappingEnabled())
7432                 shadowmapping = true;
7433
7434         if (r_shadow_usingdeferredprepass)
7435                 R_Shadow_DrawPrepass();
7436
7437         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7438         {
7439                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7440                 if (r_timereport_active)
7441                         R_TimeReport("worlddepth");
7442         }
7443         if (r_depthfirst.integer >= 2)
7444         {
7445                 R_DrawModelsDepth();
7446                 if (r_timereport_active)
7447                         R_TimeReport("modeldepth");
7448         }
7449
7450         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7451         {
7452                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7453                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7454                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7455                 // don't let sound skip if going slow
7456                 if (r_refdef.scene.extraupdate)
7457                         S_ExtraUpdate ();
7458         }
7459
7460         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7461         {
7462                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7463                 if (r_timereport_active)
7464                         R_TimeReport("world");
7465         }
7466
7467         // don't let sound skip if going slow
7468         if (r_refdef.scene.extraupdate)
7469                 S_ExtraUpdate ();
7470
7471         R_DrawModels();
7472         if (r_timereport_active)
7473                 R_TimeReport("models");
7474
7475         // don't let sound skip if going slow
7476         if (r_refdef.scene.extraupdate)
7477                 S_ExtraUpdate ();
7478
7479         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7480         {
7481                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7482                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7483                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7484                 // don't let sound skip if going slow
7485                 if (r_refdef.scene.extraupdate)
7486                         S_ExtraUpdate ();
7487         }
7488
7489         if (!r_shadow_usingdeferredprepass)
7490         {
7491                 R_Shadow_DrawLights();
7492                 if (r_timereport_active)
7493                         R_TimeReport("rtlights");
7494         }
7495
7496         // don't let sound skip if going slow
7497         if (r_refdef.scene.extraupdate)
7498                 S_ExtraUpdate ();
7499
7500         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7501         {
7502                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7503                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7504                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7505                 // don't let sound skip if going slow
7506                 if (r_refdef.scene.extraupdate)
7507                         S_ExtraUpdate ();
7508         }
7509
7510         if (cl.csqc_vidvars.drawworld)
7511         {
7512                 if (cl_decals_newsystem.integer)
7513                 {
7514                         R_DrawModelDecals();
7515                         if (r_timereport_active)
7516                                 R_TimeReport("modeldecals");
7517                 }
7518                 else
7519                 {
7520                         R_DrawDecals();
7521                         if (r_timereport_active)
7522                                 R_TimeReport("decals");
7523                 }
7524
7525                 R_DrawParticles();
7526                 if (r_timereport_active)
7527                         R_TimeReport("particles");
7528
7529                 R_DrawExplosions();
7530                 if (r_timereport_active)
7531                         R_TimeReport("explosions");
7532
7533                 R_DrawLightningBeams();
7534                 if (r_timereport_active)
7535                         R_TimeReport("lightning");
7536         }
7537
7538         if (cl.csqc_loaded)
7539                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7540
7541         if (r_refdef.view.showdebug)
7542         {
7543                 if (cl_locs_show.integer)
7544                 {
7545                         R_DrawLocs();
7546                         if (r_timereport_active)
7547                                 R_TimeReport("showlocs");
7548                 }
7549
7550                 if (r_drawportals.integer)
7551                 {
7552                         R_DrawPortals();
7553                         if (r_timereport_active)
7554                                 R_TimeReport("portals");
7555                 }
7556
7557                 if (r_showbboxes.value > 0)
7558                 {
7559                         R_DrawEntityBBoxes();
7560                         if (r_timereport_active)
7561                                 R_TimeReport("bboxes");
7562                 }
7563         }
7564
7565         if (r_transparent.integer)
7566         {
7567                 R_MeshQueue_RenderTransparent();
7568                 if (r_timereport_active)
7569                         R_TimeReport("drawtrans");
7570         }
7571
7572         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))
7573         {
7574                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7575                 if (r_timereport_active)
7576                         R_TimeReport("worlddebug");
7577                 R_DrawModelsDebug();
7578                 if (r_timereport_active)
7579                         R_TimeReport("modeldebug");
7580         }
7581
7582         if (cl.csqc_vidvars.drawworld)
7583         {
7584                 R_Shadow_DrawCoronas();
7585                 if (r_timereport_active)
7586                         R_TimeReport("coronas");
7587         }
7588
7589 #if 0
7590         {
7591                 GL_DepthTest(false);
7592                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7593                 GL_Color(1, 1, 1, 1);
7594                 qglBegin(GL_POLYGON);
7595                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7596                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7597                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7598                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7599                 qglEnd();
7600                 qglBegin(GL_POLYGON);
7601                 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]);
7602                 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]);
7603                 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]);
7604                 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]);
7605                 qglEnd();
7606                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7607         }
7608 #endif
7609
7610         // don't let sound skip if going slow
7611         if (r_refdef.scene.extraupdate)
7612                 S_ExtraUpdate ();
7613 }
7614
7615 static const unsigned short bboxelements[36] =
7616 {
7617         5, 1, 3, 5, 3, 7,
7618         6, 2, 0, 6, 0, 4,
7619         7, 3, 2, 7, 2, 6,
7620         4, 0, 1, 4, 1, 5,
7621         4, 5, 7, 4, 7, 6,
7622         1, 0, 2, 1, 2, 3,
7623 };
7624
7625 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7626 {
7627         int i;
7628         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7629
7630         RSurf_ActiveWorldEntity();
7631
7632         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7633         GL_DepthMask(false);
7634         GL_DepthRange(0, 1);
7635         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7636 //      R_Mesh_ResetTextureState();
7637
7638         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7639         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7640         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7641         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7642         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7643         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7644         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7645         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7646         R_FillColors(color4f, 8, cr, cg, cb, ca);
7647         if (r_refdef.fogenabled)
7648         {
7649                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7650                 {
7651                         f1 = RSurf_FogVertex(v);
7652                         f2 = 1 - f1;
7653                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7654                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7655                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7656                 }
7657         }
7658         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7659         R_Mesh_ResetTextureState();
7660         R_SetupShader_Generic_NoTexture(false, false);
7661         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7662 }
7663
7664 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7665 {
7666         prvm_prog_t *prog = SVVM_prog;
7667         int i;
7668         float color[4];
7669         prvm_edict_t *edict;
7670
7671         // this function draws bounding boxes of server entities
7672         if (!sv.active)
7673                 return;
7674
7675         GL_CullFace(GL_NONE);
7676         R_SetupShader_Generic_NoTexture(false, false);
7677
7678         for (i = 0;i < numsurfaces;i++)
7679         {
7680                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7681                 switch ((int)PRVM_serveredictfloat(edict, solid))
7682                 {
7683                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7684                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7685                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7686                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7687                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7688                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7689                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7690                 }
7691                 color[3] *= r_showbboxes.value;
7692                 color[3] = bound(0, color[3], 1);
7693                 GL_DepthTest(!r_showdisabledepthtest.integer);
7694                 GL_CullFace(r_refdef.view.cullface_front);
7695                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7696         }
7697 }
7698
7699 static void R_DrawEntityBBoxes(void)
7700 {
7701         int i;
7702         prvm_edict_t *edict;
7703         vec3_t center;
7704         prvm_prog_t *prog = SVVM_prog;
7705
7706         // this function draws bounding boxes of server entities
7707         if (!sv.active)
7708                 return;
7709
7710         for (i = 0;i < prog->num_edicts;i++)
7711         {
7712                 edict = PRVM_EDICT_NUM(i);
7713                 if (edict->priv.server->free)
7714                         continue;
7715                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7716                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7717                         continue;
7718                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7719                         continue;
7720                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7721                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7722         }
7723 }
7724
7725 static const int nomodelelement3i[24] =
7726 {
7727         5, 2, 0,
7728         5, 1, 2,
7729         5, 0, 3,
7730         5, 3, 1,
7731         0, 2, 4,
7732         2, 1, 4,
7733         3, 0, 4,
7734         1, 3, 4
7735 };
7736
7737 static const unsigned short nomodelelement3s[24] =
7738 {
7739         5, 2, 0,
7740         5, 1, 2,
7741         5, 0, 3,
7742         5, 3, 1,
7743         0, 2, 4,
7744         2, 1, 4,
7745         3, 0, 4,
7746         1, 3, 4
7747 };
7748
7749 static const float nomodelvertex3f[6*3] =
7750 {
7751         -16,   0,   0,
7752          16,   0,   0,
7753           0, -16,   0,
7754           0,  16,   0,
7755           0,   0, -16,
7756           0,   0,  16
7757 };
7758
7759 static const float nomodelcolor4f[6*4] =
7760 {
7761         0.0f, 0.0f, 0.5f, 1.0f,
7762         0.0f, 0.0f, 0.5f, 1.0f,
7763         0.0f, 0.5f, 0.0f, 1.0f,
7764         0.0f, 0.5f, 0.0f, 1.0f,
7765         0.5f, 0.0f, 0.0f, 1.0f,
7766         0.5f, 0.0f, 0.0f, 1.0f
7767 };
7768
7769 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7770 {
7771         int i;
7772         float f1, f2, *c;
7773         float color4f[6*4];
7774
7775         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);
7776
7777         // this is only called once per entity so numsurfaces is always 1, and
7778         // surfacelist is always {0}, so this code does not handle batches
7779
7780         if (rsurface.ent_flags & RENDER_ADDITIVE)
7781         {
7782                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7783                 GL_DepthMask(false);
7784         }
7785         else if (rsurface.colormod[3] < 1)
7786         {
7787                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7788                 GL_DepthMask(false);
7789         }
7790         else
7791         {
7792                 GL_BlendFunc(GL_ONE, GL_ZERO);
7793                 GL_DepthMask(true);
7794         }
7795         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7796         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7797         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7798         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7799         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7800         for (i = 0, c = color4f;i < 6;i++, c += 4)
7801         {
7802                 c[0] *= rsurface.colormod[0];
7803                 c[1] *= rsurface.colormod[1];
7804                 c[2] *= rsurface.colormod[2];
7805                 c[3] *= rsurface.colormod[3];
7806         }
7807         if (r_refdef.fogenabled)
7808         {
7809                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7810                 {
7811                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7812                         f2 = 1 - f1;
7813                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7814                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7815                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7816                 }
7817         }
7818 //      R_Mesh_ResetTextureState();
7819         R_SetupShader_Generic_NoTexture(false, false);
7820         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7821         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7822 }
7823
7824 void R_DrawNoModel(entity_render_t *ent)
7825 {
7826         vec3_t org;
7827         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7828         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7829                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7830         else
7831                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7832 }
7833
7834 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7835 {
7836         vec3_t right1, right2, diff, normal;
7837
7838         VectorSubtract (org2, org1, normal);
7839
7840         // calculate 'right' vector for start
7841         VectorSubtract (r_refdef.view.origin, org1, diff);
7842         CrossProduct (normal, diff, right1);
7843         VectorNormalize (right1);
7844
7845         // calculate 'right' vector for end
7846         VectorSubtract (r_refdef.view.origin, org2, diff);
7847         CrossProduct (normal, diff, right2);
7848         VectorNormalize (right2);
7849
7850         vert[ 0] = org1[0] + width * right1[0];
7851         vert[ 1] = org1[1] + width * right1[1];
7852         vert[ 2] = org1[2] + width * right1[2];
7853         vert[ 3] = org1[0] - width * right1[0];
7854         vert[ 4] = org1[1] - width * right1[1];
7855         vert[ 5] = org1[2] - width * right1[2];
7856         vert[ 6] = org2[0] - width * right2[0];
7857         vert[ 7] = org2[1] - width * right2[1];
7858         vert[ 8] = org2[2] - width * right2[2];
7859         vert[ 9] = org2[0] + width * right2[0];
7860         vert[10] = org2[1] + width * right2[1];
7861         vert[11] = org2[2] + width * right2[2];
7862 }
7863
7864 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)
7865 {
7866         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7867         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7868         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7869         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7870         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7871         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7872         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7873         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7874         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7875         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7876         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7877         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7878 }
7879
7880 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7881 {
7882         int i;
7883         float *vertex3f;
7884         float v[3];
7885         VectorSet(v, x, y, z);
7886         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7887                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7888                         break;
7889         if (i == mesh->numvertices)
7890         {
7891                 if (mesh->numvertices < mesh->maxvertices)
7892                 {
7893                         VectorCopy(v, vertex3f);
7894                         mesh->numvertices++;
7895                 }
7896                 return mesh->numvertices;
7897         }
7898         else
7899                 return i;
7900 }
7901
7902 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7903 {
7904         int i;
7905         int *e, element[3];
7906         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7907         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7908         e = mesh->element3i + mesh->numtriangles * 3;
7909         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7910         {
7911                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7912                 if (mesh->numtriangles < mesh->maxtriangles)
7913                 {
7914                         *e++ = element[0];
7915                         *e++ = element[1];
7916                         *e++ = element[2];
7917                         mesh->numtriangles++;
7918                 }
7919                 element[1] = element[2];
7920         }
7921 }
7922
7923 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7924 {
7925         int i;
7926         int *e, element[3];
7927         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7928         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7929         e = mesh->element3i + mesh->numtriangles * 3;
7930         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7931         {
7932                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7933                 if (mesh->numtriangles < mesh->maxtriangles)
7934                 {
7935                         *e++ = element[0];
7936                         *e++ = element[1];
7937                         *e++ = element[2];
7938                         mesh->numtriangles++;
7939                 }
7940                 element[1] = element[2];
7941         }
7942 }
7943
7944 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7945 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7946 {
7947         int planenum, planenum2;
7948         int w;
7949         int tempnumpoints;
7950         mplane_t *plane, *plane2;
7951         double maxdist;
7952         double temppoints[2][256*3];
7953         // figure out how large a bounding box we need to properly compute this brush
7954         maxdist = 0;
7955         for (w = 0;w < numplanes;w++)
7956                 maxdist = max(maxdist, fabs(planes[w].dist));
7957         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7958         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7959         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7960         {
7961                 w = 0;
7962                 tempnumpoints = 4;
7963                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7964                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7965                 {
7966                         if (planenum2 == planenum)
7967                                 continue;
7968                         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);
7969                         w = !w;
7970                 }
7971                 if (tempnumpoints < 3)
7972                         continue;
7973                 // generate elements forming a triangle fan for this polygon
7974                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7975         }
7976 }
7977
7978 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)
7979 {
7980         texturelayer_t *layer;
7981         layer = t->currentlayers + t->currentnumlayers++;
7982         layer->type = type;
7983         layer->depthmask = depthmask;
7984         layer->blendfunc1 = blendfunc1;
7985         layer->blendfunc2 = blendfunc2;
7986         layer->texture = texture;
7987         layer->texmatrix = *matrix;
7988         layer->color[0] = r;
7989         layer->color[1] = g;
7990         layer->color[2] = b;
7991         layer->color[3] = a;
7992 }
7993
7994 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7995 {
7996         if(parms[0] == 0 && parms[1] == 0)
7997                 return false;
7998         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7999                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8000                         return false;
8001         return true;
8002 }
8003
8004 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8005 {
8006         double index, f;
8007         index = parms[2] + rsurface.shadertime * parms[3];
8008         index -= floor(index);
8009         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8010         {
8011         default:
8012         case Q3WAVEFUNC_NONE:
8013         case Q3WAVEFUNC_NOISE:
8014         case Q3WAVEFUNC_COUNT:
8015                 f = 0;
8016                 break;
8017         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8018         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8019         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8020         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8021         case Q3WAVEFUNC_TRIANGLE:
8022                 index *= 4;
8023                 f = index - floor(index);
8024                 if (index < 1)
8025                 {
8026                         // f = f;
8027                 }
8028                 else if (index < 2)
8029                         f = 1 - f;
8030                 else if (index < 3)
8031                         f = -f;
8032                 else
8033                         f = -(1 - f);
8034                 break;
8035         }
8036         f = parms[0] + parms[1] * f;
8037         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8038                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8039         return (float) f;
8040 }
8041
8042 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8043 {
8044         int w, h, idx;
8045         float shadertime;
8046         float f;
8047         float offsetd[2];
8048         float tcmat[12];
8049         matrix4x4_t matrix, temp;
8050         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8051         // it's better to have one huge fixup every 9 hours than gradual
8052         // degradation over time which looks consistently bad after many hours.
8053         //
8054         // tcmod scroll in particular suffers from this degradation which can't be
8055         // effectively worked around even with floor() tricks because we don't
8056         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8057         // a workaround involving floor() would be incorrect anyway...
8058         shadertime = rsurface.shadertime;
8059         if (shadertime >= 32768.0f)
8060                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8061         switch(tcmod->tcmod)
8062         {
8063                 case Q3TCMOD_COUNT:
8064                 case Q3TCMOD_NONE:
8065                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8066                                 matrix = r_waterscrollmatrix;
8067                         else
8068                                 matrix = identitymatrix;
8069                         break;
8070                 case Q3TCMOD_ENTITYTRANSLATE:
8071                         // this is used in Q3 to allow the gamecode to control texcoord
8072                         // scrolling on the entity, which is not supported in darkplaces yet.
8073                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8074                         break;
8075                 case Q3TCMOD_ROTATE:
8076                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8077                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8078                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8079                         break;
8080                 case Q3TCMOD_SCALE:
8081                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8082                         break;
8083                 case Q3TCMOD_SCROLL:
8084                         // this particular tcmod is a "bug for bug" compatible one with regards to
8085                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8086                         // specifically did the wrapping and so we must mimic that...
8087                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8088                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8089                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8090                         break;
8091                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8092                         w = (int) tcmod->parms[0];
8093                         h = (int) tcmod->parms[1];
8094                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8095                         f = f - floor(f);
8096                         idx = (int) floor(f * w * h);
8097                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8098                         break;
8099                 case Q3TCMOD_STRETCH:
8100                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8101                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8102                         break;
8103                 case Q3TCMOD_TRANSFORM:
8104                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8105                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8106                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8107                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8108                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8109                         break;
8110                 case Q3TCMOD_TURBULENT:
8111                         // this is handled in the RSurf_PrepareVertices function
8112                         matrix = identitymatrix;
8113                         break;
8114         }
8115         temp = *texmatrix;
8116         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8117 }
8118
8119 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8120 {
8121         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8122         char name[MAX_QPATH];
8123         skinframe_t *skinframe;
8124         unsigned char pixels[296*194];
8125         strlcpy(cache->name, skinname, sizeof(cache->name));
8126         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8127         if (developer_loading.integer)
8128                 Con_Printf("loading %s\n", name);
8129         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8130         if (!skinframe || !skinframe->base)
8131         {
8132                 unsigned char *f;
8133                 fs_offset_t filesize;
8134                 skinframe = NULL;
8135                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8136                 if (f)
8137                 {
8138                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8139                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8140                         Mem_Free(f);
8141                 }
8142         }
8143         cache->skinframe = skinframe;
8144 }
8145
8146 texture_t *R_GetCurrentTexture(texture_t *t)
8147 {
8148         int i;
8149         const entity_render_t *ent = rsurface.entity;
8150         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8151         q3shaderinfo_layer_tcmod_t *tcmod;
8152
8153         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8154                 return t->currentframe;
8155         t->update_lastrenderframe = r_textureframe;
8156         t->update_lastrenderentity = (void *)ent;
8157
8158         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8159                 t->camera_entity = ent->entitynumber;
8160         else
8161                 t->camera_entity = 0;
8162
8163         // switch to an alternate material if this is a q1bsp animated material
8164         {
8165                 texture_t *texture = t;
8166                 int s = rsurface.ent_skinnum;
8167                 if ((unsigned int)s >= (unsigned int)model->numskins)
8168                         s = 0;
8169                 if (model->skinscenes)
8170                 {
8171                         if (model->skinscenes[s].framecount > 1)
8172                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8173                         else
8174                                 s = model->skinscenes[s].firstframe;
8175                 }
8176                 if (s > 0)
8177                         t = t + s * model->num_surfaces;
8178                 if (t->animated)
8179                 {
8180                         // use an alternate animation if the entity's frame is not 0,
8181                         // and only if the texture has an alternate animation
8182                         if (t->animated == 2) // q2bsp
8183                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8184                         else if (rsurface.ent_alttextures && t->anim_total[1])
8185                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8186                         else
8187                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8188                 }
8189                 texture->currentframe = t;
8190         }
8191
8192         // update currentskinframe to be a qw skin or animation frame
8193         if (rsurface.ent_qwskin >= 0)
8194         {
8195                 i = rsurface.ent_qwskin;
8196                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8197                 {
8198                         r_qwskincache_size = cl.maxclients;
8199                         if (r_qwskincache)
8200                                 Mem_Free(r_qwskincache);
8201                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8202                 }
8203                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8204                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8205                 t->currentskinframe = r_qwskincache[i].skinframe;
8206                 if (t->currentskinframe == NULL)
8207                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8208         }
8209         else if (t->numskinframes >= 2)
8210                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8211         if (t->backgroundnumskinframes >= 2)
8212                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8213
8214         t->currentmaterialflags = t->basematerialflags;
8215         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8216         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8217                 t->currentalpha *= r_wateralpha.value;
8218         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8219                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8220         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8221                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8222         if (!(rsurface.ent_flags & RENDER_LIGHT))
8223                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8224         else if (FAKELIGHT_ENABLED)
8225         {
8226                 // no modellight if using fakelight for the map
8227         }
8228         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8229         {
8230                 // pick a model lighting mode
8231                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8232                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8233                 else
8234                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8235         }
8236         if (rsurface.ent_flags & RENDER_ADDITIVE)
8237                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8238         else if (t->currentalpha < 1)
8239                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8240         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8241         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8242                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8243         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8244                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8245         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8246                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8247         if (t->backgroundnumskinframes)
8248                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8249         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8250         {
8251                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8252                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8253         }
8254         else
8255                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8256         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8257         {
8258                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8259                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8260         }
8261         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8262                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8263
8264         // there is no tcmod
8265         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8266         {
8267                 t->currenttexmatrix = r_waterscrollmatrix;
8268                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8269         }
8270         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8271         {
8272                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8273                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8274         }
8275
8276         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8277                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8278         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8279                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8280
8281         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8282         if (t->currentskinframe->qpixels)
8283                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8284         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8285         if (!t->basetexture)
8286                 t->basetexture = r_texture_notexture;
8287         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8288         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8289         t->nmaptexture = t->currentskinframe->nmap;
8290         if (!t->nmaptexture)
8291                 t->nmaptexture = r_texture_blanknormalmap;
8292         t->glosstexture = r_texture_black;
8293         t->glowtexture = t->currentskinframe->glow;
8294         t->fogtexture = t->currentskinframe->fog;
8295         t->reflectmasktexture = t->currentskinframe->reflect;
8296         if (t->backgroundnumskinframes)
8297         {
8298                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8299                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8300                 t->backgroundglosstexture = r_texture_black;
8301                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8302                 if (!t->backgroundnmaptexture)
8303                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8304                 // make sure that if glow is going to be used, both textures are not NULL
8305                 if (!t->backgroundglowtexture && t->glowtexture)
8306                         t->backgroundglowtexture = r_texture_black;
8307                 if (!t->glowtexture && t->backgroundglowtexture)
8308                         t->glowtexture = r_texture_black;
8309         }
8310         else
8311         {
8312                 t->backgroundbasetexture = r_texture_white;
8313                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8314                 t->backgroundglosstexture = r_texture_black;
8315                 t->backgroundglowtexture = NULL;
8316         }
8317         t->specularpower = r_shadow_glossexponent.value;
8318         // TODO: store reference values for these in the texture?
8319         t->specularscale = 0;
8320         if (r_shadow_gloss.integer > 0)
8321         {
8322                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8323                 {
8324                         if (r_shadow_glossintensity.value > 0)
8325                         {
8326                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8327                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8328                                 t->specularscale = r_shadow_glossintensity.value;
8329                         }
8330                 }
8331                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8332                 {
8333                         t->glosstexture = r_texture_white;
8334                         t->backgroundglosstexture = r_texture_white;
8335                         t->specularscale = r_shadow_gloss2intensity.value;
8336                         t->specularpower = r_shadow_gloss2exponent.value;
8337                 }
8338         }
8339         t->specularscale *= t->specularscalemod;
8340         t->specularpower *= t->specularpowermod;
8341         t->rtlightambient = 0;
8342
8343         // lightmaps mode looks bad with dlights using actual texturing, so turn
8344         // off the colormap and glossmap, but leave the normalmap on as it still
8345         // accurately represents the shading involved
8346         if (gl_lightmaps.integer)
8347         {
8348                 t->basetexture = r_texture_grey128;
8349                 t->pantstexture = r_texture_black;
8350                 t->shirttexture = r_texture_black;
8351                 if (gl_lightmaps.integer < 2)
8352                         t->nmaptexture = r_texture_blanknormalmap;
8353                 t->glosstexture = r_texture_black;
8354                 t->glowtexture = NULL;
8355                 t->fogtexture = NULL;
8356                 t->reflectmasktexture = NULL;
8357                 t->backgroundbasetexture = NULL;
8358                 if (gl_lightmaps.integer < 2)
8359                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8360                 t->backgroundglosstexture = r_texture_black;
8361                 t->backgroundglowtexture = NULL;
8362                 t->specularscale = 0;
8363                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8364         }
8365
8366         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8367         VectorClear(t->dlightcolor);
8368         t->currentnumlayers = 0;
8369         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8370         {
8371                 int blendfunc1, blendfunc2;
8372                 qboolean depthmask;
8373                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8374                 {
8375                         blendfunc1 = GL_SRC_ALPHA;
8376                         blendfunc2 = GL_ONE;
8377                 }
8378                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8379                 {
8380                         blendfunc1 = GL_SRC_ALPHA;
8381                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8382                 }
8383                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8384                 {
8385                         blendfunc1 = t->customblendfunc[0];
8386                         blendfunc2 = t->customblendfunc[1];
8387                 }
8388                 else
8389                 {
8390                         blendfunc1 = GL_ONE;
8391                         blendfunc2 = GL_ZERO;
8392                 }
8393                 // don't colormod evilblend textures
8394                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8395                         VectorSet(t->lightmapcolor, 1, 1, 1);
8396                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8397                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8398                 {
8399                         // fullbright is not affected by r_refdef.lightmapintensity
8400                         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]);
8401                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8402                                 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]);
8403                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8404                                 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]);
8405                 }
8406                 else
8407                 {
8408                         vec3_t ambientcolor;
8409                         float colorscale;
8410                         // set the color tint used for lights affecting this surface
8411                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8412                         colorscale = 2;
8413                         // q3bsp has no lightmap updates, so the lightstylevalue that
8414                         // would normally be baked into the lightmap must be
8415                         // applied to the color
8416                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8417                         if (model->type == mod_brushq3)
8418                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8419                         colorscale *= r_refdef.lightmapintensity;
8420                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8421                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8422                         // basic lit geometry
8423                         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]);
8424                         // add pants/shirt if needed
8425                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8426                                 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]);
8427                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8428                                 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]);
8429                         // now add ambient passes if needed
8430                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8431                         {
8432                                 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]);
8433                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8434                                         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]);
8435                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8436                                         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]);
8437                         }
8438                 }
8439                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8440                         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]);
8441                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8442                 {
8443                         // if this is opaque use alpha blend which will darken the earlier
8444                         // passes cheaply.
8445                         //
8446                         // if this is an alpha blended material, all the earlier passes
8447                         // were darkened by fog already, so we only need to add the fog
8448                         // color ontop through the fog mask texture
8449                         //
8450                         // if this is an additive blended material, all the earlier passes
8451                         // were darkened by fog already, and we should not add fog color
8452                         // (because the background was not darkened, there is no fog color
8453                         // that was lost behind it).
8454                         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]);
8455                 }
8456         }
8457
8458         return t;
8459 }
8460
8461 rsurfacestate_t rsurface;
8462
8463 void RSurf_ActiveWorldEntity(void)
8464 {
8465         dp_model_t *model = r_refdef.scene.worldmodel;
8466         //if (rsurface.entity == r_refdef.scene.worldentity)
8467         //      return;
8468         rsurface.entity = r_refdef.scene.worldentity;
8469         rsurface.skeleton = NULL;
8470         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8471         rsurface.ent_skinnum = 0;
8472         rsurface.ent_qwskin = -1;
8473         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8474         rsurface.shadertime = r_refdef.scene.time;
8475         rsurface.matrix = identitymatrix;
8476         rsurface.inversematrix = identitymatrix;
8477         rsurface.matrixscale = 1;
8478         rsurface.inversematrixscale = 1;
8479         R_EntityMatrix(&identitymatrix);
8480         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8481         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8482         rsurface.fograngerecip = r_refdef.fograngerecip;
8483         rsurface.fogheightfade = r_refdef.fogheightfade;
8484         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8485         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8486         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8487         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8488         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8489         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8490         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8491         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8492         rsurface.colormod[3] = 1;
8493         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);
8494         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8495         rsurface.frameblend[0].lerp = 1;
8496         rsurface.ent_alttextures = false;
8497         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8498         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8499         rsurface.entityskeletaltransform3x4 = NULL;
8500         rsurface.entityskeletaltransform3x4buffer = NULL;
8501         rsurface.entityskeletaltransform3x4offset = 0;
8502         rsurface.entityskeletaltransform3x4size = 0;;
8503         rsurface.entityskeletalnumtransforms = 0;
8504         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8505         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8506         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8507         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8508         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8509         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8510         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8511         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8512         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8513         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8514         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8515         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8516         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8517         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8518         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8519         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8520         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8521         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8522         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8523         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8524         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8525         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8526         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8527         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8528         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8529         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8531         rsurface.modelelement3i = model->surfmesh.data_element3i;
8532         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8533         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8534         rsurface.modelelement3s = model->surfmesh.data_element3s;
8535         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8536         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8537         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8538         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8539         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8540         rsurface.modelsurfaces = model->data_surfaces;
8541         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8542         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8543         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8544         rsurface.modelgeneratedvertex = false;
8545         rsurface.batchgeneratedvertex = false;
8546         rsurface.batchfirstvertex = 0;
8547         rsurface.batchnumvertices = 0;
8548         rsurface.batchfirsttriangle = 0;
8549         rsurface.batchnumtriangles = 0;
8550         rsurface.batchvertex3f  = NULL;
8551         rsurface.batchvertex3f_vertexbuffer = NULL;
8552         rsurface.batchvertex3f_bufferoffset = 0;
8553         rsurface.batchsvector3f = NULL;
8554         rsurface.batchsvector3f_vertexbuffer = NULL;
8555         rsurface.batchsvector3f_bufferoffset = 0;
8556         rsurface.batchtvector3f = NULL;
8557         rsurface.batchtvector3f_vertexbuffer = NULL;
8558         rsurface.batchtvector3f_bufferoffset = 0;
8559         rsurface.batchnormal3f  = NULL;
8560         rsurface.batchnormal3f_vertexbuffer = NULL;
8561         rsurface.batchnormal3f_bufferoffset = 0;
8562         rsurface.batchlightmapcolor4f = NULL;
8563         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8564         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8565         rsurface.batchtexcoordtexture2f = NULL;
8566         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8567         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8568         rsurface.batchtexcoordlightmap2f = NULL;
8569         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8570         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8571         rsurface.batchskeletalindex4ub = NULL;
8572         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8573         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8574         rsurface.batchskeletalweight4ub = NULL;
8575         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8576         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8577         rsurface.batchvertexmesh = NULL;
8578         rsurface.batchvertexmesh_vertexbuffer = NULL;
8579         rsurface.batchvertexmesh_bufferoffset = 0;
8580         rsurface.batchelement3i = NULL;
8581         rsurface.batchelement3i_indexbuffer = NULL;
8582         rsurface.batchelement3i_bufferoffset = 0;
8583         rsurface.batchelement3s = NULL;
8584         rsurface.batchelement3s_indexbuffer = NULL;
8585         rsurface.batchelement3s_bufferoffset = 0;
8586         rsurface.passcolor4f = NULL;
8587         rsurface.passcolor4f_vertexbuffer = NULL;
8588         rsurface.passcolor4f_bufferoffset = 0;
8589         rsurface.forcecurrenttextureupdate = false;
8590 }
8591
8592 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8593 {
8594         dp_model_t *model = ent->model;
8595         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8596         //      return;
8597         rsurface.entity = (entity_render_t *)ent;
8598         rsurface.skeleton = ent->skeleton;
8599         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8600         rsurface.ent_skinnum = ent->skinnum;
8601         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;
8602         rsurface.ent_flags = ent->flags;
8603         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8604         rsurface.matrix = ent->matrix;
8605         rsurface.inversematrix = ent->inversematrix;
8606         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8607         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8608         R_EntityMatrix(&rsurface.matrix);
8609         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8610         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8611         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8612         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8613         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8614         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8615         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8616         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8617         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8618         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8619         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8620         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8621         rsurface.colormod[3] = ent->alpha;
8622         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8623         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8624         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8625         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8626         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8627         if (ent->model->brush.submodel && !prepass)
8628         {
8629                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8630                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8631         }
8632         // if the animcache code decided it should use the shader path, skip the deform step
8633         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8634         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8635         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8636         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8637         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8638         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8639         {
8640                 if (ent->animcache_vertex3f)
8641                 {
8642                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8643                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8644                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8645                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8646                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8647                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8648                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8649                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8650                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8651                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8652                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8653                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8654                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8655                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8656                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8657                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8658                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8659                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8660                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8661                 }
8662                 else if (wanttangents)
8663                 {
8664                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8665                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8666                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8667                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8668                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8669                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8670                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8671                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8672                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8673                         rsurface.modelvertexmesh = NULL;
8674                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8675                         rsurface.modelvertexmesh_bufferoffset = 0;
8676                         rsurface.modelvertex3f_vertexbuffer = NULL;
8677                         rsurface.modelvertex3f_bufferoffset = 0;
8678                         rsurface.modelvertex3f_vertexbuffer = 0;
8679                         rsurface.modelvertex3f_bufferoffset = 0;
8680                         rsurface.modelsvector3f_vertexbuffer = 0;
8681                         rsurface.modelsvector3f_bufferoffset = 0;
8682                         rsurface.modeltvector3f_vertexbuffer = 0;
8683                         rsurface.modeltvector3f_bufferoffset = 0;
8684                         rsurface.modelnormal3f_vertexbuffer = 0;
8685                         rsurface.modelnormal3f_bufferoffset = 0;
8686                 }
8687                 else if (wantnormals)
8688                 {
8689                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8690                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8691                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8692                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8693                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8694                         rsurface.modelsvector3f = NULL;
8695                         rsurface.modeltvector3f = NULL;
8696                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8697                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8698                         rsurface.modelvertexmesh = NULL;
8699                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8700                         rsurface.modelvertexmesh_bufferoffset = 0;
8701                         rsurface.modelvertex3f_vertexbuffer = NULL;
8702                         rsurface.modelvertex3f_bufferoffset = 0;
8703                         rsurface.modelvertex3f_vertexbuffer = 0;
8704                         rsurface.modelvertex3f_bufferoffset = 0;
8705                         rsurface.modelsvector3f_vertexbuffer = 0;
8706                         rsurface.modelsvector3f_bufferoffset = 0;
8707                         rsurface.modeltvector3f_vertexbuffer = 0;
8708                         rsurface.modeltvector3f_bufferoffset = 0;
8709                         rsurface.modelnormal3f_vertexbuffer = 0;
8710                         rsurface.modelnormal3f_bufferoffset = 0;
8711                 }
8712                 else
8713                 {
8714                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8715                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8716                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8717                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8718                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8719                         rsurface.modelsvector3f = NULL;
8720                         rsurface.modeltvector3f = NULL;
8721                         rsurface.modelnormal3f = NULL;
8722                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8723                         rsurface.modelvertexmesh = NULL;
8724                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8725                         rsurface.modelvertexmesh_bufferoffset = 0;
8726                         rsurface.modelvertex3f_vertexbuffer = NULL;
8727                         rsurface.modelvertex3f_bufferoffset = 0;
8728                         rsurface.modelvertex3f_vertexbuffer = 0;
8729                         rsurface.modelvertex3f_bufferoffset = 0;
8730                         rsurface.modelsvector3f_vertexbuffer = 0;
8731                         rsurface.modelsvector3f_bufferoffset = 0;
8732                         rsurface.modeltvector3f_vertexbuffer = 0;
8733                         rsurface.modeltvector3f_bufferoffset = 0;
8734                         rsurface.modelnormal3f_vertexbuffer = 0;
8735                         rsurface.modelnormal3f_bufferoffset = 0;
8736                 }
8737                 rsurface.modelgeneratedvertex = true;
8738         }
8739         else
8740         {
8741                 if (rsurface.entityskeletaltransform3x4)
8742                 {
8743                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8744                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8745                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8746                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8747                 }
8748                 else
8749                 {
8750                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8751                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8752                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8753                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8754                 }
8755                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8756                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8757                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8758                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8759                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8760                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8761                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8762                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8763                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8764                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8765                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8766                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8767                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8768                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8769                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8770                 rsurface.modelgeneratedvertex = false;
8771         }
8772         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8773         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8774         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8775         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8776         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8777         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8778         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8779         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8780         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8781         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8782         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8783         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8784         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8785         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8786         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8787         rsurface.modelelement3i = model->surfmesh.data_element3i;
8788         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8789         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8790         rsurface.modelelement3s = model->surfmesh.data_element3s;
8791         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8792         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8793         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8794         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8795         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8796         rsurface.modelsurfaces = model->data_surfaces;
8797         rsurface.batchgeneratedvertex = false;
8798         rsurface.batchfirstvertex = 0;
8799         rsurface.batchnumvertices = 0;
8800         rsurface.batchfirsttriangle = 0;
8801         rsurface.batchnumtriangles = 0;
8802         rsurface.batchvertex3f  = NULL;
8803         rsurface.batchvertex3f_vertexbuffer = NULL;
8804         rsurface.batchvertex3f_bufferoffset = 0;
8805         rsurface.batchsvector3f = NULL;
8806         rsurface.batchsvector3f_vertexbuffer = NULL;
8807         rsurface.batchsvector3f_bufferoffset = 0;
8808         rsurface.batchtvector3f = NULL;
8809         rsurface.batchtvector3f_vertexbuffer = NULL;
8810         rsurface.batchtvector3f_bufferoffset = 0;
8811         rsurface.batchnormal3f  = NULL;
8812         rsurface.batchnormal3f_vertexbuffer = NULL;
8813         rsurface.batchnormal3f_bufferoffset = 0;
8814         rsurface.batchlightmapcolor4f = NULL;
8815         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8816         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8817         rsurface.batchtexcoordtexture2f = NULL;
8818         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8819         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8820         rsurface.batchtexcoordlightmap2f = NULL;
8821         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8822         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8823         rsurface.batchskeletalindex4ub = NULL;
8824         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8825         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8826         rsurface.batchskeletalweight4ub = NULL;
8827         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8828         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8829         rsurface.batchvertexmesh = NULL;
8830         rsurface.batchvertexmesh_vertexbuffer = NULL;
8831         rsurface.batchvertexmesh_bufferoffset = 0;
8832         rsurface.batchelement3i = NULL;
8833         rsurface.batchelement3i_indexbuffer = NULL;
8834         rsurface.batchelement3i_bufferoffset = 0;
8835         rsurface.batchelement3s = NULL;
8836         rsurface.batchelement3s_indexbuffer = NULL;
8837         rsurface.batchelement3s_bufferoffset = 0;
8838         rsurface.passcolor4f = NULL;
8839         rsurface.passcolor4f_vertexbuffer = NULL;
8840         rsurface.passcolor4f_bufferoffset = 0;
8841         rsurface.forcecurrenttextureupdate = false;
8842 }
8843
8844 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)
8845 {
8846         rsurface.entity = r_refdef.scene.worldentity;
8847         rsurface.skeleton = NULL;
8848         rsurface.ent_skinnum = 0;
8849         rsurface.ent_qwskin = -1;
8850         rsurface.ent_flags = entflags;
8851         rsurface.shadertime = r_refdef.scene.time - shadertime;
8852         rsurface.modelnumvertices = numvertices;
8853         rsurface.modelnumtriangles = numtriangles;
8854         rsurface.matrix = *matrix;
8855         rsurface.inversematrix = *inversematrix;
8856         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8857         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8858         R_EntityMatrix(&rsurface.matrix);
8859         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8860         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8861         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8862         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8863         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8864         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8865         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8866         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8867         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8868         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8869         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8870         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8871         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);
8872         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8873         rsurface.frameblend[0].lerp = 1;
8874         rsurface.ent_alttextures = false;
8875         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8876         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8877         rsurface.entityskeletaltransform3x4 = NULL;
8878         rsurface.entityskeletaltransform3x4buffer = NULL;
8879         rsurface.entityskeletaltransform3x4offset = 0;
8880         rsurface.entityskeletaltransform3x4size = 0;
8881         rsurface.entityskeletalnumtransforms = 0;
8882         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8883         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8884         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8885         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8886         if (wanttangents)
8887         {
8888                 rsurface.modelvertex3f = (float *)vertex3f;
8889                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8890                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8891                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8892         }
8893         else if (wantnormals)
8894         {
8895                 rsurface.modelvertex3f = (float *)vertex3f;
8896                 rsurface.modelsvector3f = NULL;
8897                 rsurface.modeltvector3f = NULL;
8898                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8899         }
8900         else
8901         {
8902                 rsurface.modelvertex3f = (float *)vertex3f;
8903                 rsurface.modelsvector3f = NULL;
8904                 rsurface.modeltvector3f = NULL;
8905                 rsurface.modelnormal3f = NULL;
8906         }
8907         rsurface.modelvertexmesh = NULL;
8908         rsurface.modelvertexmesh_vertexbuffer = NULL;
8909         rsurface.modelvertexmesh_bufferoffset = 0;
8910         rsurface.modelvertex3f_vertexbuffer = 0;
8911         rsurface.modelvertex3f_bufferoffset = 0;
8912         rsurface.modelsvector3f_vertexbuffer = 0;
8913         rsurface.modelsvector3f_bufferoffset = 0;
8914         rsurface.modeltvector3f_vertexbuffer = 0;
8915         rsurface.modeltvector3f_bufferoffset = 0;
8916         rsurface.modelnormal3f_vertexbuffer = 0;
8917         rsurface.modelnormal3f_bufferoffset = 0;
8918         rsurface.modelgeneratedvertex = true;
8919         rsurface.modellightmapcolor4f  = (float *)color4f;
8920         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8921         rsurface.modellightmapcolor4f_bufferoffset = 0;
8922         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8923         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8924         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8925         rsurface.modeltexcoordlightmap2f  = NULL;
8926         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8927         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8928         rsurface.modelskeletalindex4ub = NULL;
8929         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8930         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8931         rsurface.modelskeletalweight4ub = NULL;
8932         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8933         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8934         rsurface.modelelement3i = (int *)element3i;
8935         rsurface.modelelement3i_indexbuffer = NULL;
8936         rsurface.modelelement3i_bufferoffset = 0;
8937         rsurface.modelelement3s = (unsigned short *)element3s;
8938         rsurface.modelelement3s_indexbuffer = NULL;
8939         rsurface.modelelement3s_bufferoffset = 0;
8940         rsurface.modellightmapoffsets = NULL;
8941         rsurface.modelsurfaces = NULL;
8942         rsurface.batchgeneratedvertex = false;
8943         rsurface.batchfirstvertex = 0;
8944         rsurface.batchnumvertices = 0;
8945         rsurface.batchfirsttriangle = 0;
8946         rsurface.batchnumtriangles = 0;
8947         rsurface.batchvertex3f  = NULL;
8948         rsurface.batchvertex3f_vertexbuffer = NULL;
8949         rsurface.batchvertex3f_bufferoffset = 0;
8950         rsurface.batchsvector3f = NULL;
8951         rsurface.batchsvector3f_vertexbuffer = NULL;
8952         rsurface.batchsvector3f_bufferoffset = 0;
8953         rsurface.batchtvector3f = NULL;
8954         rsurface.batchtvector3f_vertexbuffer = NULL;
8955         rsurface.batchtvector3f_bufferoffset = 0;
8956         rsurface.batchnormal3f  = NULL;
8957         rsurface.batchnormal3f_vertexbuffer = NULL;
8958         rsurface.batchnormal3f_bufferoffset = 0;
8959         rsurface.batchlightmapcolor4f = NULL;
8960         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8961         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8962         rsurface.batchtexcoordtexture2f = NULL;
8963         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8964         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8965         rsurface.batchtexcoordlightmap2f = NULL;
8966         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8967         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8968         rsurface.batchskeletalindex4ub = NULL;
8969         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8970         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8971         rsurface.batchskeletalweight4ub = NULL;
8972         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8973         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8974         rsurface.batchvertexmesh = NULL;
8975         rsurface.batchvertexmesh_vertexbuffer = NULL;
8976         rsurface.batchvertexmesh_bufferoffset = 0;
8977         rsurface.batchelement3i = NULL;
8978         rsurface.batchelement3i_indexbuffer = NULL;
8979         rsurface.batchelement3i_bufferoffset = 0;
8980         rsurface.batchelement3s = NULL;
8981         rsurface.batchelement3s_indexbuffer = NULL;
8982         rsurface.batchelement3s_bufferoffset = 0;
8983         rsurface.passcolor4f = NULL;
8984         rsurface.passcolor4f_vertexbuffer = NULL;
8985         rsurface.passcolor4f_bufferoffset = 0;
8986         rsurface.forcecurrenttextureupdate = true;
8987
8988         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8989         {
8990                 if ((wantnormals || wanttangents) && !normal3f)
8991                 {
8992                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8993                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8994                 }
8995                 if (wanttangents && !svector3f)
8996                 {
8997                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8998                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8999                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9000                 }
9001         }
9002 }
9003
9004 float RSurf_FogPoint(const float *v)
9005 {
9006         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9007         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9008         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9009         float FogHeightFade = r_refdef.fogheightfade;
9010         float fogfrac;
9011         unsigned int fogmasktableindex;
9012         if (r_refdef.fogplaneviewabove)
9013                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9014         else
9015                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9016         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9017         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9018 }
9019
9020 float RSurf_FogVertex(const float *v)
9021 {
9022         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9023         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9024         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9025         float FogHeightFade = rsurface.fogheightfade;
9026         float fogfrac;
9027         unsigned int fogmasktableindex;
9028         if (r_refdef.fogplaneviewabove)
9029                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9030         else
9031                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9032         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9033         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9034 }
9035
9036 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9037 {
9038         int i;
9039         for (i = 0;i < numelements;i++)
9040                 outelement3i[i] = inelement3i[i] + adjust;
9041 }
9042
9043 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9044 extern cvar_t gl_vbo;
9045 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9046 {
9047         int deformindex;
9048         int firsttriangle;
9049         int numtriangles;
9050         int firstvertex;
9051         int endvertex;
9052         int numvertices;
9053         int surfacefirsttriangle;
9054         int surfacenumtriangles;
9055         int surfacefirstvertex;
9056         int surfaceendvertex;
9057         int surfacenumvertices;
9058         int batchnumsurfaces = texturenumsurfaces;
9059         int batchnumvertices;
9060         int batchnumtriangles;
9061         int needsupdate;
9062         int i, j;
9063         qboolean gaps;
9064         qboolean dynamicvertex;
9065         float amplitude;
9066         float animpos;
9067         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9068         float waveparms[4];
9069         unsigned char *ub;
9070         q3shaderinfo_deform_t *deform;
9071         const msurface_t *surface, *firstsurface;
9072         r_vertexmesh_t *vertexmesh;
9073         if (!texturenumsurfaces)
9074                 return;
9075         // find vertex range of this surface batch
9076         gaps = false;
9077         firstsurface = texturesurfacelist[0];
9078         firsttriangle = firstsurface->num_firsttriangle;
9079         batchnumvertices = 0;
9080         batchnumtriangles = 0;
9081         firstvertex = endvertex = firstsurface->num_firstvertex;
9082         for (i = 0;i < texturenumsurfaces;i++)
9083         {
9084                 surface = texturesurfacelist[i];
9085                 if (surface != firstsurface + i)
9086                         gaps = true;
9087                 surfacefirstvertex = surface->num_firstvertex;
9088                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9089                 surfacenumvertices = surface->num_vertices;
9090                 surfacenumtriangles = surface->num_triangles;
9091                 if (firstvertex > surfacefirstvertex)
9092                         firstvertex = surfacefirstvertex;
9093                 if (endvertex < surfaceendvertex)
9094                         endvertex = surfaceendvertex;
9095                 batchnumvertices += surfacenumvertices;
9096                 batchnumtriangles += surfacenumtriangles;
9097         }
9098
9099         r_refdef.stats[r_stat_batch_batches]++;
9100         if (gaps)
9101                 r_refdef.stats[r_stat_batch_withgaps]++;
9102         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9103         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9104         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9105
9106         // we now know the vertex range used, and if there are any gaps in it
9107         rsurface.batchfirstvertex = firstvertex;
9108         rsurface.batchnumvertices = endvertex - firstvertex;
9109         rsurface.batchfirsttriangle = firsttriangle;
9110         rsurface.batchnumtriangles = batchnumtriangles;
9111
9112         // this variable holds flags for which properties have been updated that
9113         // may require regenerating vertexmesh array...
9114         needsupdate = 0;
9115
9116         // check if any dynamic vertex processing must occur
9117         dynamicvertex = false;
9118
9119         // a cvar to force the dynamic vertex path to be taken, for debugging
9120         if (r_batch_debugdynamicvertexpath.integer)
9121         {
9122                 if (!dynamicvertex)
9123                 {
9124                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9125                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9126                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9127                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9128                 }
9129                 dynamicvertex = true;
9130         }
9131
9132         // if there is a chance of animated vertex colors, it's a dynamic batch
9133         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9134         {
9135                 if (!dynamicvertex)
9136                 {
9137                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9138                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9139                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9140                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9141                 }
9142                 dynamicvertex = true;
9143                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9144         }
9145
9146         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9147         {
9148                 switch (deform->deform)
9149                 {
9150                 default:
9151                 case Q3DEFORM_PROJECTIONSHADOW:
9152                 case Q3DEFORM_TEXT0:
9153                 case Q3DEFORM_TEXT1:
9154                 case Q3DEFORM_TEXT2:
9155                 case Q3DEFORM_TEXT3:
9156                 case Q3DEFORM_TEXT4:
9157                 case Q3DEFORM_TEXT5:
9158                 case Q3DEFORM_TEXT6:
9159                 case Q3DEFORM_TEXT7:
9160                 case Q3DEFORM_NONE:
9161                         break;
9162                 case Q3DEFORM_AUTOSPRITE:
9163                         if (!dynamicvertex)
9164                         {
9165                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9166                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9167                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9168                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9169                         }
9170                         dynamicvertex = true;
9171                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9172                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9173                         break;
9174                 case Q3DEFORM_AUTOSPRITE2:
9175                         if (!dynamicvertex)
9176                         {
9177                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9178                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9179                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9180                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9181                         }
9182                         dynamicvertex = true;
9183                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9184                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9185                         break;
9186                 case Q3DEFORM_NORMAL:
9187                         if (!dynamicvertex)
9188                         {
9189                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9190                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9191                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9192                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9193                         }
9194                         dynamicvertex = true;
9195                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9196                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9197                         break;
9198                 case Q3DEFORM_WAVE:
9199                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9200                                 break; // if wavefunc is a nop, ignore this transform
9201                         if (!dynamicvertex)
9202                         {
9203                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9204                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9205                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9206                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9207                         }
9208                         dynamicvertex = true;
9209                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9210                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9211                         break;
9212                 case Q3DEFORM_BULGE:
9213                         if (!dynamicvertex)
9214                         {
9215                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9216                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9217                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9218                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9219                         }
9220                         dynamicvertex = true;
9221                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9222                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9223                         break;
9224                 case Q3DEFORM_MOVE:
9225                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9226                                 break; // if wavefunc is a nop, ignore this transform
9227                         if (!dynamicvertex)
9228                         {
9229                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9230                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9231                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9232                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9233                         }
9234                         dynamicvertex = true;
9235                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9236                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9237                         break;
9238                 }
9239         }
9240         switch(rsurface.texture->tcgen.tcgen)
9241         {
9242         default:
9243         case Q3TCGEN_TEXTURE:
9244                 break;
9245         case Q3TCGEN_LIGHTMAP:
9246                 if (!dynamicvertex)
9247                 {
9248                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9249                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9250                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9251                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9252                 }
9253                 dynamicvertex = true;
9254                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9255                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9256                 break;
9257         case Q3TCGEN_VECTOR:
9258                 if (!dynamicvertex)
9259                 {
9260                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9261                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9262                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9263                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9264                 }
9265                 dynamicvertex = true;
9266                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9267                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9268                 break;
9269         case Q3TCGEN_ENVIRONMENT:
9270                 if (!dynamicvertex)
9271                 {
9272                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9273                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9274                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9275                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9276                 }
9277                 dynamicvertex = true;
9278                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9279                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9280                 break;
9281         }
9282         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9283         {
9284                 if (!dynamicvertex)
9285                 {
9286                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9287                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9288                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9289                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9290                 }
9291                 dynamicvertex = true;
9292                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9293                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9294         }
9295
9296         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9297         {
9298                 if (!dynamicvertex)
9299                 {
9300                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9301                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9302                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9303                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9304                 }
9305                 dynamicvertex = true;
9306                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9307         }
9308
9309         // when the model data has no vertex buffer (dynamic mesh), we need to
9310         // eliminate gaps
9311         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9312                 batchneed |= BATCHNEED_NOGAPS;
9313
9314         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9315         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9316         // we ensure this by treating the vertex batch as dynamic...
9317         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9318         {
9319                 if (!dynamicvertex)
9320                 {
9321                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9322                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9323                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9324                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9325                 }
9326                 dynamicvertex = true;
9327         }
9328
9329         if (dynamicvertex)
9330         {
9331                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9332                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9333                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9334                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9335                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9336                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9337                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9338                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9339         }
9340
9341         // if needsupdate, we have to do a dynamic vertex batch for sure
9342         if (needsupdate & batchneed)
9343         {
9344                 if (!dynamicvertex)
9345                 {
9346                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9347                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9348                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9349                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9350                 }
9351                 dynamicvertex = true;
9352         }
9353
9354         // see if we need to build vertexmesh from arrays
9355         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9356         {
9357                 if (!dynamicvertex)
9358                 {
9359                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9360                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9361                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9362                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9363                 }
9364                 dynamicvertex = true;
9365         }
9366
9367         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9368         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9369                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9370
9371         rsurface.batchvertex3f = rsurface.modelvertex3f;
9372         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9373         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9374         rsurface.batchsvector3f = rsurface.modelsvector3f;
9375         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9376         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9377         rsurface.batchtvector3f = rsurface.modeltvector3f;
9378         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9379         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9380         rsurface.batchnormal3f = rsurface.modelnormal3f;
9381         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9382         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9383         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9384         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9385         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9386         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9387         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9388         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9389         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9390         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9391         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9392         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9393         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9394         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9395         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9396         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9397         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9398         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9399         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9400         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9401         rsurface.batchelement3i = rsurface.modelelement3i;
9402         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9403         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9404         rsurface.batchelement3s = rsurface.modelelement3s;
9405         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9406         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9407         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9408         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9409         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9410         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9411         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9412
9413         // if any dynamic vertex processing has to occur in software, we copy the
9414         // entire surface list together before processing to rebase the vertices
9415         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9416         //
9417         // if any gaps exist and we do not have a static vertex buffer, we have to
9418         // copy the surface list together to avoid wasting upload bandwidth on the
9419         // vertices in the gaps.
9420         //
9421         // if gaps exist and we have a static vertex buffer, we can choose whether
9422         // to combine the index buffer ranges into one dynamic index buffer or
9423         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9424         //
9425         // in many cases the batch is reduced to one draw call.
9426
9427         rsurface.batchmultidraw = false;
9428         rsurface.batchmultidrawnumsurfaces = 0;
9429         rsurface.batchmultidrawsurfacelist = NULL;
9430
9431         if (!dynamicvertex)
9432         {
9433                 // static vertex data, just set pointers...
9434                 rsurface.batchgeneratedvertex = false;
9435                 // if there are gaps, we want to build a combined index buffer,
9436                 // otherwise use the original static buffer with an appropriate offset
9437                 if (gaps)
9438                 {
9439                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9440                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9441                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9442                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9443                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9444                         {
9445                                 rsurface.batchmultidraw = true;
9446                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9447                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9448                                 return;
9449                         }
9450                         // build a new triangle elements array for this batch
9451                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9452                         rsurface.batchfirsttriangle = 0;
9453                         numtriangles = 0;
9454                         for (i = 0;i < texturenumsurfaces;i++)
9455                         {
9456                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9457                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9458                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9459                                 numtriangles += surfacenumtriangles;
9460                         }
9461                         rsurface.batchelement3i_indexbuffer = NULL;
9462                         rsurface.batchelement3i_bufferoffset = 0;
9463                         rsurface.batchelement3s = NULL;
9464                         rsurface.batchelement3s_indexbuffer = NULL;
9465                         rsurface.batchelement3s_bufferoffset = 0;
9466                         if (endvertex <= 65536)
9467                         {
9468                                 // make a 16bit (unsigned short) index array if possible
9469                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9470                                 for (i = 0;i < numtriangles*3;i++)
9471                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9472                         }
9473                         // upload buffer data for the copytriangles batch
9474                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9475                         {
9476                                 if (rsurface.batchelement3s)
9477                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9478                                 else if (rsurface.batchelement3i)
9479                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9480                         }
9481                 }
9482                 else
9483                 {
9484                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9485                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9486                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9487                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9488                 }
9489                 return;
9490         }
9491
9492         // something needs software processing, do it for real...
9493         // we only directly handle separate array data in this case and then
9494         // generate interleaved data if needed...
9495         rsurface.batchgeneratedvertex = true;
9496         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9497         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9498         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9499         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9500
9501         // now copy the vertex data into a combined array and make an index array
9502         // (this is what Quake3 does all the time)
9503         // we also apply any skeletal animation here that would have been done in
9504         // the vertex shader, because most of the dynamic vertex animation cases
9505         // need actual vertex positions and normals
9506         //if (dynamicvertex)
9507         {
9508                 rsurface.batchvertexmesh = NULL;
9509                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9510                 rsurface.batchvertexmesh_bufferoffset = 0;
9511                 rsurface.batchvertex3f = NULL;
9512                 rsurface.batchvertex3f_vertexbuffer = NULL;
9513                 rsurface.batchvertex3f_bufferoffset = 0;
9514                 rsurface.batchsvector3f = NULL;
9515                 rsurface.batchsvector3f_vertexbuffer = NULL;
9516                 rsurface.batchsvector3f_bufferoffset = 0;
9517                 rsurface.batchtvector3f = NULL;
9518                 rsurface.batchtvector3f_vertexbuffer = NULL;
9519                 rsurface.batchtvector3f_bufferoffset = 0;
9520                 rsurface.batchnormal3f = NULL;
9521                 rsurface.batchnormal3f_vertexbuffer = NULL;
9522                 rsurface.batchnormal3f_bufferoffset = 0;
9523                 rsurface.batchlightmapcolor4f = NULL;
9524                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9525                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9526                 rsurface.batchtexcoordtexture2f = NULL;
9527                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9528                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9529                 rsurface.batchtexcoordlightmap2f = NULL;
9530                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9531                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9532                 rsurface.batchskeletalindex4ub = NULL;
9533                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9534                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9535                 rsurface.batchskeletalweight4ub = NULL;
9536                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9537                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9538                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9539                 rsurface.batchelement3i_indexbuffer = NULL;
9540                 rsurface.batchelement3i_bufferoffset = 0;
9541                 rsurface.batchelement3s = NULL;
9542                 rsurface.batchelement3s_indexbuffer = NULL;
9543                 rsurface.batchelement3s_bufferoffset = 0;
9544                 rsurface.batchskeletaltransform3x4buffer = NULL;
9545                 rsurface.batchskeletaltransform3x4offset = 0;
9546                 rsurface.batchskeletaltransform3x4size = 0;
9547                 // we'll only be setting up certain arrays as needed
9548                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9549                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9550                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9551                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9552                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9553                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9554                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9555                 {
9556                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9557                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9558                 }
9559                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9560                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9561                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9562                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9563                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9564                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9565                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9566                 {
9567                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9568                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9569                 }
9570                 numvertices = 0;
9571                 numtriangles = 0;
9572                 for (i = 0;i < texturenumsurfaces;i++)
9573                 {
9574                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9575                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9576                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9577                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9578                         // copy only the data requested
9579                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9580                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9581                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9582                         {
9583                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9584                                 {
9585                                         if (rsurface.batchvertex3f)
9586                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9587                                         else
9588                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9589                                 }
9590                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9591                                 {
9592                                         if (rsurface.modelnormal3f)
9593                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9594                                         else
9595                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9596                                 }
9597                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9598                                 {
9599                                         if (rsurface.modelsvector3f)
9600                                         {
9601                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9602                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9603                                         }
9604                                         else
9605                                         {
9606                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9607                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9608                                         }
9609                                 }
9610                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9611                                 {
9612                                         if (rsurface.modellightmapcolor4f)
9613                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9614                                         else
9615                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9616                                 }
9617                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9618                                 {
9619                                         if (rsurface.modeltexcoordtexture2f)
9620                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9621                                         else
9622                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9623                                 }
9624                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9625                                 {
9626                                         if (rsurface.modeltexcoordlightmap2f)
9627                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9628                                         else
9629                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9630                                 }
9631                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9632                                 {
9633                                         if (rsurface.modelskeletalindex4ub)
9634                                         {
9635                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9636                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9637                                         }
9638                                         else
9639                                         {
9640                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9641                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9642                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9643                                                 for (j = 0;j < surfacenumvertices;j++)
9644                                                         ub[j*4] = 255;
9645                                         }
9646                                 }
9647                         }
9648                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9649                         numvertices += surfacenumvertices;
9650                         numtriangles += surfacenumtriangles;
9651                 }
9652
9653                 // generate a 16bit index array as well if possible
9654                 // (in general, dynamic batches fit)
9655                 if (numvertices <= 65536)
9656                 {
9657                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9658                         for (i = 0;i < numtriangles*3;i++)
9659                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9660                 }
9661
9662                 // since we've copied everything, the batch now starts at 0
9663                 rsurface.batchfirstvertex = 0;
9664                 rsurface.batchnumvertices = batchnumvertices;
9665                 rsurface.batchfirsttriangle = 0;
9666                 rsurface.batchnumtriangles = batchnumtriangles;
9667         }
9668
9669         // apply skeletal animation that would have been done in the vertex shader
9670         if (rsurface.batchskeletaltransform3x4)
9671         {
9672                 const unsigned char *si;
9673                 const unsigned char *sw;
9674                 const float *t[4];
9675                 const float *b = rsurface.batchskeletaltransform3x4;
9676                 float *vp, *vs, *vt, *vn;
9677                 float w[4];
9678                 float m[3][4], n[3][4];
9679                 float tp[3], ts[3], tt[3], tn[3];
9680                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9681                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9682                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9683                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9684                 si = rsurface.batchskeletalindex4ub;
9685                 sw = rsurface.batchskeletalweight4ub;
9686                 vp = rsurface.batchvertex3f;
9687                 vs = rsurface.batchsvector3f;
9688                 vt = rsurface.batchtvector3f;
9689                 vn = rsurface.batchnormal3f;
9690                 memset(m[0], 0, sizeof(m));
9691                 memset(n[0], 0, sizeof(n));
9692                 for (i = 0;i < batchnumvertices;i++)
9693                 {
9694                         t[0] = b + si[0]*12;
9695                         if (sw[0] == 255)
9696                         {
9697                                 // common case - only one matrix
9698                                 m[0][0] = t[0][ 0];
9699                                 m[0][1] = t[0][ 1];
9700                                 m[0][2] = t[0][ 2];
9701                                 m[0][3] = t[0][ 3];
9702                                 m[1][0] = t[0][ 4];
9703                                 m[1][1] = t[0][ 5];
9704                                 m[1][2] = t[0][ 6];
9705                                 m[1][3] = t[0][ 7];
9706                                 m[2][0] = t[0][ 8];
9707                                 m[2][1] = t[0][ 9];
9708                                 m[2][2] = t[0][10];
9709                                 m[2][3] = t[0][11];
9710                         }
9711                         else if (sw[2] + sw[3])
9712                         {
9713                                 // blend 4 matrices
9714                                 t[1] = b + si[1]*12;
9715                                 t[2] = b + si[2]*12;
9716                                 t[3] = b + si[3]*12;
9717                                 w[0] = sw[0] * (1.0f / 255.0f);
9718                                 w[1] = sw[1] * (1.0f / 255.0f);
9719                                 w[2] = sw[2] * (1.0f / 255.0f);
9720                                 w[3] = sw[3] * (1.0f / 255.0f);
9721                                 // blend the matrices
9722                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9723                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9724                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9725                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9726                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9727                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9728                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9729                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9730                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9731                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9732                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9733                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9734                         }
9735                         else
9736                         {
9737                                 // blend 2 matrices
9738                                 t[1] = b + si[1]*12;
9739                                 w[0] = sw[0] * (1.0f / 255.0f);
9740                                 w[1] = sw[1] * (1.0f / 255.0f);
9741                                 // blend the matrices
9742                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9743                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9744                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9745                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9746                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9747                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9748                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9749                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9750                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9751                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9752                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9753                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9754                         }
9755                         si += 4;
9756                         sw += 4;
9757                         // modify the vertex
9758                         VectorCopy(vp, tp);
9759                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9760                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9761                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9762                         vp += 3;
9763                         if (vn)
9764                         {
9765                                 // the normal transformation matrix is a set of cross products...
9766                                 CrossProduct(m[1], m[2], n[0]);
9767                                 CrossProduct(m[2], m[0], n[1]);
9768                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9769                                 VectorCopy(vn, tn);
9770                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9771                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9772                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9773                                 VectorNormalize(vn);
9774                                 vn += 3;
9775                                 if (vs)
9776                                 {
9777                                         VectorCopy(vs, ts);
9778                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9779                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9780                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9781                                         VectorNormalize(vs);
9782                                         vs += 3;
9783                                         VectorCopy(vt, tt);
9784                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9785                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9786                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9787                                         VectorNormalize(vt);
9788                                         vt += 3;
9789                                 }
9790                         }
9791                 }
9792                 rsurface.batchskeletaltransform3x4 = NULL;
9793                 rsurface.batchskeletalnumtransforms = 0;
9794         }
9795
9796         // q1bsp surfaces rendered in vertex color mode have to have colors
9797         // calculated based on lightstyles
9798         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9799         {
9800                 // generate color arrays for the surfaces in this list
9801                 int c[4];
9802                 int scale;
9803                 int size3;
9804                 const int *offsets;
9805                 const unsigned char *lm;
9806                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9807                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9808                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9809                 numvertices = 0;
9810                 for (i = 0;i < texturenumsurfaces;i++)
9811                 {
9812                         surface = texturesurfacelist[i];
9813                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9814                         surfacenumvertices = surface->num_vertices;
9815                         if (surface->lightmapinfo->samples)
9816                         {
9817                                 for (j = 0;j < surfacenumvertices;j++)
9818                                 {
9819                                         lm = surface->lightmapinfo->samples + offsets[j];
9820                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9821                                         VectorScale(lm, scale, c);
9822                                         if (surface->lightmapinfo->styles[1] != 255)
9823                                         {
9824                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9825                                                 lm += size3;
9826                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9827                                                 VectorMA(c, scale, lm, c);
9828                                                 if (surface->lightmapinfo->styles[2] != 255)
9829                                                 {
9830                                                         lm += size3;
9831                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9832                                                         VectorMA(c, scale, lm, c);
9833                                                         if (surface->lightmapinfo->styles[3] != 255)
9834                                                         {
9835                                                                 lm += size3;
9836                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9837                                                                 VectorMA(c, scale, lm, c);
9838                                                         }
9839                                                 }
9840                                         }
9841                                         c[0] >>= 7;
9842                                         c[1] >>= 7;
9843                                         c[2] >>= 7;
9844                                         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);
9845                                         numvertices++;
9846                                 }
9847                         }
9848                         else
9849                         {
9850                                 for (j = 0;j < surfacenumvertices;j++)
9851                                 {
9852                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9853                                         numvertices++;
9854                                 }
9855                         }
9856                 }
9857         }
9858
9859         // if vertices are deformed (sprite flares and things in maps, possibly
9860         // water waves, bulges and other deformations), modify the copied vertices
9861         // in place
9862         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9863         {
9864                 float scale;
9865                 switch (deform->deform)
9866                 {
9867                 default:
9868                 case Q3DEFORM_PROJECTIONSHADOW:
9869                 case Q3DEFORM_TEXT0:
9870                 case Q3DEFORM_TEXT1:
9871                 case Q3DEFORM_TEXT2:
9872                 case Q3DEFORM_TEXT3:
9873                 case Q3DEFORM_TEXT4:
9874                 case Q3DEFORM_TEXT5:
9875                 case Q3DEFORM_TEXT6:
9876                 case Q3DEFORM_TEXT7:
9877                 case Q3DEFORM_NONE:
9878                         break;
9879                 case Q3DEFORM_AUTOSPRITE:
9880                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9881                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9882                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9883                         VectorNormalize(newforward);
9884                         VectorNormalize(newright);
9885                         VectorNormalize(newup);
9886 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9887 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9888 //                      rsurface.batchvertex3f_bufferoffset = 0;
9889 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9890 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9891 //                      rsurface.batchsvector3f_bufferoffset = 0;
9892 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9893 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9894 //                      rsurface.batchtvector3f_bufferoffset = 0;
9895 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9896 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9897 //                      rsurface.batchnormal3f_bufferoffset = 0;
9898                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9899                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9900                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9901                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9902                                 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);
9903                         // a single autosprite surface can contain multiple sprites...
9904                         for (j = 0;j < batchnumvertices - 3;j += 4)
9905                         {
9906                                 VectorClear(center);
9907                                 for (i = 0;i < 4;i++)
9908                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9909                                 VectorScale(center, 0.25f, center);
9910                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9911                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9912                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9913                                 for (i = 0;i < 4;i++)
9914                                 {
9915                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9916                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9917                                 }
9918                         }
9919                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9920                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9921                         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);
9922                         break;
9923                 case Q3DEFORM_AUTOSPRITE2:
9924                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9925                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9926                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9927                         VectorNormalize(newforward);
9928                         VectorNormalize(newright);
9929                         VectorNormalize(newup);
9930 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9931 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9932 //                      rsurface.batchvertex3f_bufferoffset = 0;
9933                         {
9934                                 const float *v1, *v2;
9935                                 vec3_t start, end;
9936                                 float f, l;
9937                                 struct
9938                                 {
9939                                         float length2;
9940                                         const float *v1;
9941                                         const float *v2;
9942                                 }
9943                                 shortest[2];
9944                                 memset(shortest, 0, sizeof(shortest));
9945                                 // a single autosprite surface can contain multiple sprites...
9946                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9947                                 {
9948                                         VectorClear(center);
9949                                         for (i = 0;i < 4;i++)
9950                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9951                                         VectorScale(center, 0.25f, center);
9952                                         // find the two shortest edges, then use them to define the
9953                                         // axis vectors for rotating around the central axis
9954                                         for (i = 0;i < 6;i++)
9955                                         {
9956                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9957                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9958                                                 l = VectorDistance2(v1, v2);
9959                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9960                                                 if (v1[2] != v2[2])
9961                                                         l += (1.0f / 1024.0f);
9962                                                 if (shortest[0].length2 > l || i == 0)
9963                                                 {
9964                                                         shortest[1] = shortest[0];
9965                                                         shortest[0].length2 = l;
9966                                                         shortest[0].v1 = v1;
9967                                                         shortest[0].v2 = v2;
9968                                                 }
9969                                                 else if (shortest[1].length2 > l || i == 1)
9970                                                 {
9971                                                         shortest[1].length2 = l;
9972                                                         shortest[1].v1 = v1;
9973                                                         shortest[1].v2 = v2;
9974                                                 }
9975                                         }
9976                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9977                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9978                                         // this calculates the right vector from the shortest edge
9979                                         // and the up vector from the edge midpoints
9980                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9981                                         VectorNormalize(right);
9982                                         VectorSubtract(end, start, up);
9983                                         VectorNormalize(up);
9984                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9985                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9986                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9987                                         VectorNegate(forward, forward);
9988                                         VectorReflect(forward, 0, up, forward);
9989                                         VectorNormalize(forward);
9990                                         CrossProduct(up, forward, newright);
9991                                         VectorNormalize(newright);
9992                                         // rotate the quad around the up axis vector, this is made
9993                                         // especially easy by the fact we know the quad is flat,
9994                                         // so we only have to subtract the center position and
9995                                         // measure distance along the right vector, and then
9996                                         // multiply that by the newright vector and add back the
9997                                         // center position
9998                                         // we also need to subtract the old position to undo the
9999                                         // displacement from the center, which we do with a
10000                                         // DotProduct, the subtraction/addition of center is also
10001                                         // optimized into DotProducts here
10002                                         l = DotProduct(right, center);
10003                                         for (i = 0;i < 4;i++)
10004                                         {
10005                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10006                                                 f = DotProduct(right, v1) - l;
10007                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10008                                         }
10009                                 }
10010                         }
10011                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10012                         {
10013 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10014 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10015 //                              rsurface.batchnormal3f_bufferoffset = 0;
10016                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10017                         }
10018                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10019                         {
10020 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10021 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10022 //                              rsurface.batchsvector3f_bufferoffset = 0;
10023 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10024 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10025 //                              rsurface.batchtvector3f_bufferoffset = 0;
10026                                 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);
10027                         }
10028                         break;
10029                 case Q3DEFORM_NORMAL:
10030                         // deform the normals to make reflections wavey
10031                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10032                         rsurface.batchnormal3f_vertexbuffer = NULL;
10033                         rsurface.batchnormal3f_bufferoffset = 0;
10034                         for (j = 0;j < batchnumvertices;j++)
10035                         {
10036                                 float vertex[3];
10037                                 float *normal = rsurface.batchnormal3f + 3*j;
10038                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10039                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10040                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10041                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10042                                 VectorNormalize(normal);
10043                         }
10044                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10045                         {
10046 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10047 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10048 //                              rsurface.batchsvector3f_bufferoffset = 0;
10049 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10050 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10051 //                              rsurface.batchtvector3f_bufferoffset = 0;
10052                                 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);
10053                         }
10054                         break;
10055                 case Q3DEFORM_WAVE:
10056                         // deform vertex array to make wavey water and flags and such
10057                         waveparms[0] = deform->waveparms[0];
10058                         waveparms[1] = deform->waveparms[1];
10059                         waveparms[2] = deform->waveparms[2];
10060                         waveparms[3] = deform->waveparms[3];
10061                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10062                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10063                         // this is how a divisor of vertex influence on deformation
10064                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10065                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10066 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10067 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10068 //                      rsurface.batchvertex3f_bufferoffset = 0;
10069 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10070 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10071 //                      rsurface.batchnormal3f_bufferoffset = 0;
10072                         for (j = 0;j < batchnumvertices;j++)
10073                         {
10074                                 // if the wavefunc depends on time, evaluate it per-vertex
10075                                 if (waveparms[3])
10076                                 {
10077                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10078                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10079                                 }
10080                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10081                         }
10082                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10083                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10084                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10085                         {
10086 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10087 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10088 //                              rsurface.batchsvector3f_bufferoffset = 0;
10089 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10090 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10091 //                              rsurface.batchtvector3f_bufferoffset = 0;
10092                                 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);
10093                         }
10094                         break;
10095                 case Q3DEFORM_BULGE:
10096                         // deform vertex array to make the surface have moving bulges
10097 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10098 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10099 //                      rsurface.batchvertex3f_bufferoffset = 0;
10100 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10101 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10102 //                      rsurface.batchnormal3f_bufferoffset = 0;
10103                         for (j = 0;j < batchnumvertices;j++)
10104                         {
10105                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10106                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10107                         }
10108                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10109                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10110                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10111                         {
10112 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10113 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10114 //                              rsurface.batchsvector3f_bufferoffset = 0;
10115 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10116 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10117 //                              rsurface.batchtvector3f_bufferoffset = 0;
10118                                 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);
10119                         }
10120                         break;
10121                 case Q3DEFORM_MOVE:
10122                         // deform vertex array
10123                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10124                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10125                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10126                         VectorScale(deform->parms, scale, waveparms);
10127 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10128 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10129 //                      rsurface.batchvertex3f_bufferoffset = 0;
10130                         for (j = 0;j < batchnumvertices;j++)
10131                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10132                         break;
10133                 }
10134         }
10135
10136         if (rsurface.batchtexcoordtexture2f)
10137         {
10138         // generate texcoords based on the chosen texcoord source
10139                 switch(rsurface.texture->tcgen.tcgen)
10140                 {
10141                 default:
10142                 case Q3TCGEN_TEXTURE:
10143                         break;
10144                 case Q3TCGEN_LIGHTMAP:
10145         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10146         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10147         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10148                         if (rsurface.batchtexcoordlightmap2f)
10149                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10150                         break;
10151                 case Q3TCGEN_VECTOR:
10152         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10153         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10154         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10155                         for (j = 0;j < batchnumvertices;j++)
10156                         {
10157                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10158                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10159                         }
10160                         break;
10161                 case Q3TCGEN_ENVIRONMENT:
10162                         // make environment reflections using a spheremap
10163                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10164                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10165                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10166                         for (j = 0;j < batchnumvertices;j++)
10167                         {
10168                                 // identical to Q3A's method, but executed in worldspace so
10169                                 // carried models can be shiny too
10170
10171                                 float viewer[3], d, reflected[3], worldreflected[3];
10172
10173                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10174                                 // VectorNormalize(viewer);
10175
10176                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10177
10178                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10179                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10180                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10181                                 // note: this is proportinal to viewer, so we can normalize later
10182
10183                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10184                                 VectorNormalize(worldreflected);
10185
10186                                 // note: this sphere map only uses world x and z!
10187                                 // so positive and negative y will LOOK THE SAME.
10188                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10189                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10190                         }
10191                         break;
10192                 }
10193                 // the only tcmod that needs software vertex processing is turbulent, so
10194                 // check for it here and apply the changes if needed
10195                 // and we only support that as the first one
10196                 // (handling a mixture of turbulent and other tcmods would be problematic
10197                 //  without punting it entirely to a software path)
10198                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10199                 {
10200                         amplitude = rsurface.texture->tcmods[0].parms[1];
10201                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10202         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10203         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10204         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10205                         for (j = 0;j < batchnumvertices;j++)
10206                         {
10207                                 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);
10208                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10209                         }
10210                 }
10211         }
10212
10213         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10214         {
10215                 // convert the modified arrays to vertex structs
10216 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10217 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10218 //              rsurface.batchvertexmesh_bufferoffset = 0;
10219                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10220                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10221                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10222                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10223                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10224                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10225                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10226                 {
10227                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10228                         {
10229                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10230                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10231                         }
10232                 }
10233                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10234                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10235                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10236                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10237                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10238                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10239                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10240                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10241                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10242                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10243                 {
10244                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10245                         {
10246                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10247                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10248                         }
10249                 }
10250         }
10251
10252         // upload buffer data for the dynamic batch
10253         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10254         {
10255                 if (rsurface.batchvertexmesh)
10256                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10257                 else
10258                 {
10259                         if (rsurface.batchvertex3f)
10260                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10261                         if (rsurface.batchsvector3f)
10262                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10263                         if (rsurface.batchtvector3f)
10264                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10265                         if (rsurface.batchnormal3f)
10266                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10267                         if (rsurface.batchlightmapcolor4f)
10268                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10269                         if (rsurface.batchtexcoordtexture2f)
10270                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10271                         if (rsurface.batchtexcoordlightmap2f)
10272                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10273                         if (rsurface.batchskeletalindex4ub)
10274                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10275                         if (rsurface.batchskeletalweight4ub)
10276                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10277                 }
10278                 if (rsurface.batchelement3s)
10279                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10280                 else if (rsurface.batchelement3i)
10281                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10282         }
10283 }
10284
10285 void RSurf_DrawBatch(void)
10286 {
10287         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10288         // through the pipeline, killing it earlier in the pipeline would have
10289         // per-surface overhead rather than per-batch overhead, so it's best to
10290         // reject it here, before it hits glDraw.
10291         if (rsurface.batchnumtriangles == 0)
10292                 return;
10293 #if 0
10294         // batch debugging code
10295         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10296         {
10297                 int i;
10298                 int j;
10299                 int c;
10300                 const int *e;
10301                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10302                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10303                 {
10304                         c = e[i];
10305                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10306                         {
10307                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10308                                 {
10309                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10310                                                 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);
10311                                         break;
10312                                 }
10313                         }
10314                 }
10315         }
10316 #endif
10317         if (rsurface.batchmultidraw)
10318         {
10319                 // issue multiple draws rather than copying index data
10320                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10321                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10322                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10323                 for (i = 0;i < numsurfaces;)
10324                 {
10325                         // combine consecutive surfaces as one draw
10326                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10327                                 if (surfacelist[j] != surfacelist[k] + 1)
10328                                         break;
10329                         firstvertex = surfacelist[i]->num_firstvertex;
10330                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10331                         firsttriangle = surfacelist[i]->num_firsttriangle;
10332                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10333                         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);
10334                         i = j;
10335                 }
10336         }
10337         else
10338         {
10339                 // there is only one consecutive run of index data (may have been combined)
10340                 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);
10341         }
10342 }
10343
10344 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10345 {
10346         // pick the closest matching water plane
10347         int planeindex, vertexindex, bestplaneindex = -1;
10348         float d, bestd;
10349         vec3_t vert;
10350         const float *v;
10351         r_waterstate_waterplane_t *p;
10352         qboolean prepared = false;
10353         bestd = 0;
10354         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10355         {
10356                 if(p->camera_entity != rsurface.texture->camera_entity)
10357                         continue;
10358                 d = 0;
10359                 if(!prepared)
10360                 {
10361                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10362                         prepared = true;
10363                         if(rsurface.batchnumvertices == 0)
10364                                 break;
10365                 }
10366                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10367                 {
10368                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10369                         d += fabs(PlaneDiff(vert, &p->plane));
10370                 }
10371                 if (bestd > d || bestplaneindex < 0)
10372                 {
10373                         bestd = d;
10374                         bestplaneindex = planeindex;
10375                 }
10376         }
10377         return bestplaneindex;
10378         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10379         // this situation though, as it might be better to render single larger
10380         // batches with useless stuff (backface culled for example) than to
10381         // render multiple smaller batches
10382 }
10383
10384 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10385 {
10386         int i;
10387         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388         rsurface.passcolor4f_vertexbuffer = 0;
10389         rsurface.passcolor4f_bufferoffset = 0;
10390         for (i = 0;i < rsurface.batchnumvertices;i++)
10391                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10392 }
10393
10394 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10395 {
10396         int i;
10397         float f;
10398         const float *v;
10399         const float *c;
10400         float *c2;
10401         if (rsurface.passcolor4f)
10402         {
10403                 // generate color arrays
10404                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10405                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10406                 rsurface.passcolor4f_vertexbuffer = 0;
10407                 rsurface.passcolor4f_bufferoffset = 0;
10408                 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)
10409                 {
10410                         f = RSurf_FogVertex(v);
10411                         c2[0] = c[0] * f;
10412                         c2[1] = c[1] * f;
10413                         c2[2] = c[2] * f;
10414                         c2[3] = c[3];
10415                 }
10416         }
10417         else
10418         {
10419                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10420                 rsurface.passcolor4f_vertexbuffer = 0;
10421                 rsurface.passcolor4f_bufferoffset = 0;
10422                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10423                 {
10424                         f = RSurf_FogVertex(v);
10425                         c2[0] = f;
10426                         c2[1] = f;
10427                         c2[2] = f;
10428                         c2[3] = 1;
10429                 }
10430         }
10431 }
10432
10433 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10434 {
10435         int i;
10436         float f;
10437         const float *v;
10438         const float *c;
10439         float *c2;
10440         if (!rsurface.passcolor4f)
10441                 return;
10442         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
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, c += 4, c2 += 4)
10447         {
10448                 f = RSurf_FogVertex(v);
10449                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10450                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10451                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10452                 c2[3] = c[3];
10453         }
10454 }
10455
10456 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10457 {
10458         int i;
10459         const float *c;
10460         float *c2;
10461         if (!rsurface.passcolor4f)
10462                 return;
10463         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10464         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10465         rsurface.passcolor4f_vertexbuffer = 0;
10466         rsurface.passcolor4f_bufferoffset = 0;
10467         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10468         {
10469                 c2[0] = c[0] * r;
10470                 c2[1] = c[1] * g;
10471                 c2[2] = c[2] * b;
10472                 c2[3] = c[3] * a;
10473         }
10474 }
10475
10476 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10477 {
10478         int i;
10479         const float *c;
10480         float *c2;
10481         if (!rsurface.passcolor4f)
10482                 return;
10483         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10484         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10485         rsurface.passcolor4f_vertexbuffer = 0;
10486         rsurface.passcolor4f_bufferoffset = 0;
10487         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10488         {
10489                 c2[0] = c[0] + r_refdef.scene.ambient;
10490                 c2[1] = c[1] + r_refdef.scene.ambient;
10491                 c2[2] = c[2] + r_refdef.scene.ambient;
10492                 c2[3] = c[3];
10493         }
10494 }
10495
10496 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10497 {
10498         // TODO: optimize
10499         rsurface.passcolor4f = NULL;
10500         rsurface.passcolor4f_vertexbuffer = 0;
10501         rsurface.passcolor4f_bufferoffset = 0;
10502         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10503         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10504         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10505         GL_Color(r, g, b, a);
10506         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10507         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10508         R_Mesh_TexMatrix(0, NULL);
10509         RSurf_DrawBatch();
10510 }
10511
10512 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10513 {
10514         // TODO: optimize applyfog && applycolor case
10515         // just apply fog if necessary, and tint the fog color array if necessary
10516         rsurface.passcolor4f = NULL;
10517         rsurface.passcolor4f_vertexbuffer = 0;
10518         rsurface.passcolor4f_bufferoffset = 0;
10519         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10520         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10521         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10522         GL_Color(r, g, b, a);
10523         RSurf_DrawBatch();
10524 }
10525
10526 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10527 {
10528         // TODO: optimize
10529         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10530         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10531         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10532         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10533         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10534         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10535         GL_Color(r, g, b, a);
10536         RSurf_DrawBatch();
10537 }
10538
10539 static void RSurf_DrawBatch_GL11_ClampColor(void)
10540 {
10541         int i;
10542         const float *c1;
10543         float *c2;
10544         if (!rsurface.passcolor4f)
10545                 return;
10546         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10547         {
10548                 c2[0] = bound(0.0f, c1[0], 1.0f);
10549                 c2[1] = bound(0.0f, c1[1], 1.0f);
10550                 c2[2] = bound(0.0f, c1[2], 1.0f);
10551                 c2[3] = bound(0.0f, c1[3], 1.0f);
10552         }
10553 }
10554
10555 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10556 {
10557         int i;
10558         float f;
10559         const float *v;
10560         const float *n;
10561         float *c;
10562         //vec3_t eyedir;
10563
10564         // fake shading
10565         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10566         rsurface.passcolor4f_vertexbuffer = 0;
10567         rsurface.passcolor4f_bufferoffset = 0;
10568         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)
10569         {
10570                 f = -DotProduct(r_refdef.view.forward, n);
10571                 f = max(0, f);
10572                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10573                 f *= r_refdef.lightmapintensity;
10574                 Vector4Set(c, f, f, f, 1);
10575         }
10576 }
10577
10578 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10579 {
10580         RSurf_DrawBatch_GL11_ApplyFakeLight();
10581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10584         GL_Color(r, g, b, a);
10585         RSurf_DrawBatch();
10586 }
10587
10588 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10589 {
10590         int i;
10591         float f;
10592         float alpha;
10593         const float *v;
10594         const float *n;
10595         float *c;
10596         vec3_t ambientcolor;
10597         vec3_t diffusecolor;
10598         vec3_t lightdir;
10599         // TODO: optimize
10600         // model lighting
10601         VectorCopy(rsurface.modellight_lightdir, lightdir);
10602         f = 0.5f * r_refdef.lightmapintensity;
10603         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10604         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10605         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10606         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10607         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10608         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10609         alpha = *a;
10610         if (VectorLength2(diffusecolor) > 0)
10611         {
10612                 // q3-style directional shading
10613                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10614                 rsurface.passcolor4f_vertexbuffer = 0;
10615                 rsurface.passcolor4f_bufferoffset = 0;
10616                 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)
10617                 {
10618                         if ((f = DotProduct(n, lightdir)) > 0)
10619                                 VectorMA(ambientcolor, f, diffusecolor, c);
10620                         else
10621                                 VectorCopy(ambientcolor, c);
10622                         c[3] = alpha;
10623                 }
10624                 *r = 1;
10625                 *g = 1;
10626                 *b = 1;
10627                 *a = 1;
10628                 *applycolor = false;
10629         }
10630         else
10631         {
10632                 *r = ambientcolor[0];
10633                 *g = ambientcolor[1];
10634                 *b = ambientcolor[2];
10635                 rsurface.passcolor4f = NULL;
10636                 rsurface.passcolor4f_vertexbuffer = 0;
10637                 rsurface.passcolor4f_bufferoffset = 0;
10638         }
10639 }
10640
10641 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10642 {
10643         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10644         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10645         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10646         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10647         GL_Color(r, g, b, a);
10648         RSurf_DrawBatch();
10649 }
10650
10651 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10652 {
10653         int i;
10654         float f;
10655         const float *v;
10656         float *c;
10657
10658         // fake shading
10659         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10660         rsurface.passcolor4f_vertexbuffer = 0;
10661         rsurface.passcolor4f_bufferoffset = 0;
10662
10663         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10664         {
10665                 f = 1 - RSurf_FogVertex(v);
10666                 c[0] = r;
10667                 c[1] = g;
10668                 c[2] = b;
10669                 c[3] = f * a;
10670         }
10671 }
10672
10673 void RSurf_SetupDepthAndCulling(void)
10674 {
10675         // submodels are biased to avoid z-fighting with world surfaces that they
10676         // may be exactly overlapping (avoids z-fighting artifacts on certain
10677         // doors and things in Quake maps)
10678         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10679         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10680         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10681         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10682 }
10683
10684 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10685 {
10686         // transparent sky would be ridiculous
10687         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10688                 return;
10689         R_SetupShader_Generic_NoTexture(false, false);
10690         skyrenderlater = true;
10691         RSurf_SetupDepthAndCulling();
10692         GL_DepthMask(true);
10693         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10694         // skymasking on them, and Quake3 never did sky masking (unlike
10695         // software Quake and software Quake2), so disable the sky masking
10696         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10697         // and skymasking also looks very bad when noclipping outside the
10698         // level, so don't use it then either.
10699         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10700         {
10701                 R_Mesh_ResetTextureState();
10702                 if (skyrendermasked)
10703                 {
10704                         R_SetupShader_DepthOrShadow(false, false, false);
10705                         // depth-only (masking)
10706                         GL_ColorMask(0,0,0,0);
10707                         // just to make sure that braindead drivers don't draw
10708                         // anything despite that colormask...
10709                         GL_BlendFunc(GL_ZERO, GL_ONE);
10710                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10711                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10712                 }
10713                 else
10714                 {
10715                         R_SetupShader_Generic_NoTexture(false, false);
10716                         // fog sky
10717                         GL_BlendFunc(GL_ONE, GL_ZERO);
10718                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10719                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10720                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10721                 }
10722                 RSurf_DrawBatch();
10723                 if (skyrendermasked)
10724                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10725         }
10726         R_Mesh_ResetTextureState();
10727         GL_Color(1, 1, 1, 1);
10728 }
10729
10730 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10731 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10732 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10733 {
10734         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10735                 return;
10736         if (prepass)
10737         {
10738                 // render screenspace normalmap to texture
10739                 GL_DepthMask(true);
10740                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10741                 RSurf_DrawBatch();
10742                 return;
10743         }
10744
10745         // bind lightmap texture
10746
10747         // water/refraction/reflection/camera surfaces have to be handled specially
10748         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10749         {
10750                 int start, end, startplaneindex;
10751                 for (start = 0;start < texturenumsurfaces;start = end)
10752                 {
10753                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10754                         if(startplaneindex < 0)
10755                         {
10756                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10757                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10758                                 end = start + 1;
10759                                 continue;
10760                         }
10761                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10762                                 ;
10763                         // now that we have a batch using the same planeindex, render it
10764                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10765                         {
10766                                 // render water or distortion background
10767                                 GL_DepthMask(true);
10768                                 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);
10769                                 RSurf_DrawBatch();
10770                                 // blend surface on top
10771                                 GL_DepthMask(false);
10772                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10773                                 RSurf_DrawBatch();
10774                         }
10775                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10776                         {
10777                                 // render surface with reflection texture as input
10778                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10779                                 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);
10780                                 RSurf_DrawBatch();
10781                         }
10782                 }
10783                 return;
10784         }
10785
10786         // render surface batch normally
10787         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10788         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);
10789         RSurf_DrawBatch();
10790 }
10791
10792 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10793 {
10794         // OpenGL 1.3 path - anything not completely ancient
10795         qboolean applycolor;
10796         qboolean applyfog;
10797         int layerindex;
10798         const texturelayer_t *layer;
10799         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);
10800         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10801
10802         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10803         {
10804                 vec4_t layercolor;
10805                 int layertexrgbscale;
10806                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10807                 {
10808                         if (layerindex == 0)
10809                                 GL_AlphaTest(true);
10810                         else
10811                         {
10812                                 GL_AlphaTest(false);
10813                                 GL_DepthFunc(GL_EQUAL);
10814                         }
10815                 }
10816                 GL_DepthMask(layer->depthmask && writedepth);
10817                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10818                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10819                 {
10820                         layertexrgbscale = 4;
10821                         VectorScale(layer->color, 0.25f, layercolor);
10822                 }
10823                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10824                 {
10825                         layertexrgbscale = 2;
10826                         VectorScale(layer->color, 0.5f, layercolor);
10827                 }
10828                 else
10829                 {
10830                         layertexrgbscale = 1;
10831                         VectorScale(layer->color, 1.0f, layercolor);
10832                 }
10833                 layercolor[3] = layer->color[3];
10834                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10835                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10836                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10837                 switch (layer->type)
10838                 {
10839                 case TEXTURELAYERTYPE_LITTEXTURE:
10840                         // single-pass lightmapped texture with 2x rgbscale
10841                         R_Mesh_TexBind(0, r_texture_white);
10842                         R_Mesh_TexMatrix(0, NULL);
10843                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10844                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10845                         R_Mesh_TexBind(1, layer->texture);
10846                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10847                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10848                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10849                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10850                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10851                         else if (FAKELIGHT_ENABLED)
10852                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10853                         else if (rsurface.uselightmaptexture)
10854                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10855                         else
10856                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10857                         break;
10858                 case TEXTURELAYERTYPE_TEXTURE:
10859                         // singletexture unlit texture with transparency support
10860                         R_Mesh_TexBind(0, layer->texture);
10861                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10862                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10863                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10864                         R_Mesh_TexBind(1, 0);
10865                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10866                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10867                         break;
10868                 case TEXTURELAYERTYPE_FOG:
10869                         // singletexture fogging
10870                         if (layer->texture)
10871                         {
10872                                 R_Mesh_TexBind(0, layer->texture);
10873                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10874                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10875                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10876                         }
10877                         else
10878                         {
10879                                 R_Mesh_TexBind(0, 0);
10880                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10881                         }
10882                         R_Mesh_TexBind(1, 0);
10883                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10884                         // generate a color array for the fog pass
10885                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10886                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10887                         RSurf_DrawBatch();
10888                         break;
10889                 default:
10890                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10891                 }
10892         }
10893         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10894         {
10895                 GL_DepthFunc(GL_LEQUAL);
10896                 GL_AlphaTest(false);
10897         }
10898 }
10899
10900 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10901 {
10902         // OpenGL 1.1 - crusty old voodoo path
10903         qboolean applyfog;
10904         int layerindex;
10905         const texturelayer_t *layer;
10906         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);
10907         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10908
10909         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10910         {
10911                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10912                 {
10913                         if (layerindex == 0)
10914                                 GL_AlphaTest(true);
10915                         else
10916                         {
10917                                 GL_AlphaTest(false);
10918                                 GL_DepthFunc(GL_EQUAL);
10919                         }
10920                 }
10921                 GL_DepthMask(layer->depthmask && writedepth);
10922                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10923                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10924                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10925                 switch (layer->type)
10926                 {
10927                 case TEXTURELAYERTYPE_LITTEXTURE:
10928                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10929                         {
10930                                 // two-pass lit texture with 2x rgbscale
10931                                 // first the lightmap pass
10932                                 R_Mesh_TexBind(0, r_texture_white);
10933                                 R_Mesh_TexMatrix(0, NULL);
10934                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10935                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10936                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10937                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10938                                 else if (FAKELIGHT_ENABLED)
10939                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10940                                 else if (rsurface.uselightmaptexture)
10941                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10942                                 else
10943                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10944                                 // then apply the texture to it
10945                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10946                                 R_Mesh_TexBind(0, layer->texture);
10947                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10948                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10949                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10950                                 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);
10951                         }
10952                         else
10953                         {
10954                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10955                                 R_Mesh_TexBind(0, layer->texture);
10956                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10957                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10958                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10959                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10960                                         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);
10961                                 else if (FAKELIGHT_ENABLED)
10962                                         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);
10963                                 else
10964                                         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);
10965                         }
10966                         break;
10967                 case TEXTURELAYERTYPE_TEXTURE:
10968                         // singletexture unlit texture with transparency support
10969                         R_Mesh_TexBind(0, layer->texture);
10970                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10971                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10972                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10973                         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);
10974                         break;
10975                 case TEXTURELAYERTYPE_FOG:
10976                         // singletexture fogging
10977                         if (layer->texture)
10978                         {
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                         }
10984                         else
10985                         {
10986                                 R_Mesh_TexBind(0, 0);
10987                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10988                         }
10989                         // generate a color array for the fog pass
10990                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10991                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10992                         RSurf_DrawBatch();
10993                         break;
10994                 default:
10995                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10996                 }
10997         }
10998         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10999         {
11000                 GL_DepthFunc(GL_LEQUAL);
11001                 GL_AlphaTest(false);
11002         }
11003 }
11004
11005 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11006 {
11007         int vi;
11008         int j;
11009         r_vertexgeneric_t *batchvertex;
11010         float c[4];
11011
11012 //      R_Mesh_ResetTextureState();
11013         R_SetupShader_Generic_NoTexture(false, false);
11014
11015         if(rsurface.texture && rsurface.texture->currentskinframe)
11016         {
11017                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11018                 c[3] *= rsurface.texture->currentalpha;
11019         }
11020         else
11021         {
11022                 c[0] = 1;
11023                 c[1] = 0;
11024                 c[2] = 1;
11025                 c[3] = 1;
11026         }
11027
11028         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11029         {
11030                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11031                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11032                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11033         }
11034
11035         // brighten it up (as texture value 127 means "unlit")
11036         c[0] *= 2 * r_refdef.view.colorscale;
11037         c[1] *= 2 * r_refdef.view.colorscale;
11038         c[2] *= 2 * r_refdef.view.colorscale;
11039
11040         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11041                 c[3] *= r_wateralpha.value;
11042
11043         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11044         {
11045                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11046                 GL_DepthMask(false);
11047         }
11048         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11049         {
11050                 GL_BlendFunc(GL_ONE, GL_ONE);
11051                 GL_DepthMask(false);
11052         }
11053         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11054         {
11055                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11056                 GL_DepthMask(false);
11057         }
11058         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11059         {
11060                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11061                 GL_DepthMask(false);
11062         }
11063         else
11064         {
11065                 GL_BlendFunc(GL_ONE, GL_ZERO);
11066                 GL_DepthMask(writedepth);
11067         }
11068
11069         if (r_showsurfaces.integer == 3)
11070         {
11071                 rsurface.passcolor4f = NULL;
11072
11073                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11074                 {
11075                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11076
11077                         rsurface.passcolor4f = NULL;
11078                         rsurface.passcolor4f_vertexbuffer = 0;
11079                         rsurface.passcolor4f_bufferoffset = 0;
11080                 }
11081                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11082                 {
11083                         qboolean applycolor = true;
11084                         float one = 1.0;
11085
11086                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11087
11088                         r_refdef.lightmapintensity = 1;
11089                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11090                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11091                 }
11092                 else if (FAKELIGHT_ENABLED)
11093                 {
11094                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11095
11096                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11097                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11098                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11099                 }
11100                 else
11101                 {
11102                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11103
11104                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11105                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11106                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11107                 }
11108
11109                 if(!rsurface.passcolor4f)
11110                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11111
11112                 RSurf_DrawBatch_GL11_ApplyAmbient();
11113                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11114                 if(r_refdef.fogenabled)
11115                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11116                 RSurf_DrawBatch_GL11_ClampColor();
11117
11118                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11119                 R_SetupShader_Generic_NoTexture(false, false);
11120                 RSurf_DrawBatch();
11121         }
11122         else if (!r_refdef.view.showdebug)
11123         {
11124                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11125                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11126                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11127                 {
11128                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11129                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11130                 }
11131                 R_Mesh_PrepareVertices_Generic_Unlock();
11132                 RSurf_DrawBatch();
11133         }
11134         else if (r_showsurfaces.integer == 4)
11135         {
11136                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11137                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11138                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11139                 {
11140                         unsigned char d = (vi << 3) * (1.0f / 256.0f);
11141                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11142                         Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11143                 }
11144                 R_Mesh_PrepareVertices_Generic_Unlock();
11145                 RSurf_DrawBatch();
11146         }
11147         else if (r_showsurfaces.integer == 2)
11148         {
11149                 const int *e;
11150                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11151                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11152                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11153                 {
11154                         unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11155                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11156                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11157                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11158                         Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11159                         Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11160                         Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11161                 }
11162                 R_Mesh_PrepareVertices_Generic_Unlock();
11163                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11164         }
11165         else
11166         {
11167                 int texturesurfaceindex;
11168                 int k;
11169                 const msurface_t *surface;
11170                 float surfacecolor4f[4];
11171                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11172                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11173                 vi = 0;
11174                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11175                 {
11176                         surface = texturesurfacelist[texturesurfaceindex];
11177                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11178                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11179                         for (j = 0;j < surface->num_vertices;j++)
11180                         {
11181                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11182                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11183                                 vi++;
11184                         }
11185                 }
11186                 R_Mesh_PrepareVertices_Generic_Unlock();
11187                 RSurf_DrawBatch();
11188         }
11189 }
11190
11191 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11192 {
11193         CHECKGLERROR
11194         RSurf_SetupDepthAndCulling();
11195         if (r_showsurfaces.integer)
11196         {
11197                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11198                 return;
11199         }
11200         switch (vid.renderpath)
11201         {
11202         case RENDERPATH_GL20:
11203         case RENDERPATH_D3D9:
11204         case RENDERPATH_D3D10:
11205         case RENDERPATH_D3D11:
11206         case RENDERPATH_SOFT:
11207         case RENDERPATH_GLES2:
11208                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11209                 break;
11210         case RENDERPATH_GL13:
11211         case RENDERPATH_GLES1:
11212                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11213                 break;
11214         case RENDERPATH_GL11:
11215                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11216                 break;
11217         }
11218         CHECKGLERROR
11219 }
11220
11221 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11222 {
11223         CHECKGLERROR
11224         RSurf_SetupDepthAndCulling();
11225         if (r_showsurfaces.integer)
11226         {
11227                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11228                 return;
11229         }
11230         switch (vid.renderpath)
11231         {
11232         case RENDERPATH_GL20:
11233         case RENDERPATH_D3D9:
11234         case RENDERPATH_D3D10:
11235         case RENDERPATH_D3D11:
11236         case RENDERPATH_SOFT:
11237         case RENDERPATH_GLES2:
11238                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11239                 break;
11240         case RENDERPATH_GL13:
11241         case RENDERPATH_GLES1:
11242                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11243                 break;
11244         case RENDERPATH_GL11:
11245                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11246                 break;
11247         }
11248         CHECKGLERROR
11249 }
11250
11251 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11252 {
11253         int i, j;
11254         int texturenumsurfaces, endsurface;
11255         texture_t *texture;
11256         const msurface_t *surface;
11257         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11258
11259         // if the model is static it doesn't matter what value we give for
11260         // wantnormals and wanttangents, so this logic uses only rules applicable
11261         // to a model, knowing that they are meaningless otherwise
11262         if (ent == r_refdef.scene.worldentity)
11263                 RSurf_ActiveWorldEntity();
11264         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11265                 RSurf_ActiveModelEntity(ent, false, false, false);
11266         else
11267         {
11268                 switch (vid.renderpath)
11269                 {
11270                 case RENDERPATH_GL20:
11271                 case RENDERPATH_D3D9:
11272                 case RENDERPATH_D3D10:
11273                 case RENDERPATH_D3D11:
11274                 case RENDERPATH_SOFT:
11275                 case RENDERPATH_GLES2:
11276                         RSurf_ActiveModelEntity(ent, true, true, false);
11277                         break;
11278                 case RENDERPATH_GL11:
11279                 case RENDERPATH_GL13:
11280                 case RENDERPATH_GLES1:
11281                         RSurf_ActiveModelEntity(ent, true, false, false);
11282                         break;
11283                 }
11284         }
11285
11286         if (r_transparentdepthmasking.integer)
11287         {
11288                 qboolean setup = false;
11289                 for (i = 0;i < numsurfaces;i = j)
11290                 {
11291                         j = i + 1;
11292                         surface = rsurface.modelsurfaces + surfacelist[i];
11293                         texture = surface->texture;
11294                         rsurface.texture = R_GetCurrentTexture(texture);
11295                         rsurface.lightmaptexture = NULL;
11296                         rsurface.deluxemaptexture = NULL;
11297                         rsurface.uselightmaptexture = false;
11298                         // scan ahead until we find a different texture
11299                         endsurface = min(i + 1024, numsurfaces);
11300                         texturenumsurfaces = 0;
11301                         texturesurfacelist[texturenumsurfaces++] = surface;
11302                         for (;j < endsurface;j++)
11303                         {
11304                                 surface = rsurface.modelsurfaces + surfacelist[j];
11305                                 if (texture != surface->texture)
11306                                         break;
11307                                 texturesurfacelist[texturenumsurfaces++] = surface;
11308                         }
11309                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11310                                 continue;
11311                         // render the range of surfaces as depth
11312                         if (!setup)
11313                         {
11314                                 setup = true;
11315                                 GL_ColorMask(0,0,0,0);
11316                                 GL_Color(1,1,1,1);
11317                                 GL_DepthTest(true);
11318                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11319                                 GL_DepthMask(true);
11320 //                              R_Mesh_ResetTextureState();
11321                         }
11322                         RSurf_SetupDepthAndCulling();
11323                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11324                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11325                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11326                         RSurf_DrawBatch();
11327                 }
11328                 if (setup)
11329                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11330         }
11331
11332         for (i = 0;i < numsurfaces;i = j)
11333         {
11334                 j = i + 1;
11335                 surface = rsurface.modelsurfaces + surfacelist[i];
11336                 texture = surface->texture;
11337                 rsurface.texture = R_GetCurrentTexture(texture);
11338                 // scan ahead until we find a different texture
11339                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11340                 texturenumsurfaces = 0;
11341                 texturesurfacelist[texturenumsurfaces++] = surface;
11342                 if(FAKELIGHT_ENABLED)
11343                 {
11344                         rsurface.lightmaptexture = NULL;
11345                         rsurface.deluxemaptexture = NULL;
11346                         rsurface.uselightmaptexture = false;
11347                         for (;j < endsurface;j++)
11348                         {
11349                                 surface = rsurface.modelsurfaces + surfacelist[j];
11350                                 if (texture != surface->texture)
11351                                         break;
11352                                 texturesurfacelist[texturenumsurfaces++] = surface;
11353                         }
11354                 }
11355                 else
11356                 {
11357                         rsurface.lightmaptexture = surface->lightmaptexture;
11358                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11359                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11360                         for (;j < endsurface;j++)
11361                         {
11362                                 surface = rsurface.modelsurfaces + surfacelist[j];
11363                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11364                                         break;
11365                                 texturesurfacelist[texturenumsurfaces++] = surface;
11366                         }
11367                 }
11368                 // render the range of surfaces
11369                 if (ent == r_refdef.scene.worldentity)
11370                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11371                 else
11372                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11373         }
11374         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11375 }
11376
11377 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11378 {
11379         // transparent surfaces get pushed off into the transparent queue
11380         int surfacelistindex;
11381         const msurface_t *surface;
11382         vec3_t tempcenter, center;
11383         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11384         {
11385                 surface = texturesurfacelist[surfacelistindex];
11386                 if (r_transparent_sortsurfacesbynearest.integer)
11387                 {
11388                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11389                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11390                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11391                 }
11392                 else
11393                 {
11394                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11395                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11396                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11397                 }
11398                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11399                 if (rsurface.entity->transparent_offset) // transparent offset
11400                 {
11401                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11402                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11403                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11404                 }
11405                 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);
11406         }
11407 }
11408
11409 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11410 {
11411         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11412                 return;
11413         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11414                 return;
11415         RSurf_SetupDepthAndCulling();
11416         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11417         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11418         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11419         RSurf_DrawBatch();
11420 }
11421
11422 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11423 {
11424         CHECKGLERROR
11425         if (depthonly)
11426                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11427         else if (prepass)
11428         {
11429                 if (!rsurface.texture->currentnumlayers)
11430                         return;
11431                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11432                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11433                 else
11434                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11435         }
11436         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11437                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11438         else if (!rsurface.texture->currentnumlayers)
11439                 return;
11440         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11441         {
11442                 // in the deferred case, transparent surfaces were queued during prepass
11443                 if (!r_shadow_usingdeferredprepass)
11444                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11445         }
11446         else
11447         {
11448                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11449                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11450         }
11451         CHECKGLERROR
11452 }
11453
11454 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11455 {
11456         int i, j;
11457         texture_t *texture;
11458         R_FrameData_SetMark();
11459         // break the surface list down into batches by texture and use of lightmapping
11460         for (i = 0;i < numsurfaces;i = j)
11461         {
11462                 j = i + 1;
11463                 // texture is the base texture pointer, rsurface.texture is the
11464                 // current frame/skin the texture is directing us to use (for example
11465                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11466                 // use skin 1 instead)
11467                 texture = surfacelist[i]->texture;
11468                 rsurface.texture = R_GetCurrentTexture(texture);
11469                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11470                 {
11471                         // if this texture is not the kind we want, skip ahead to the next one
11472                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11473                                 ;
11474                         continue;
11475                 }
11476                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11477                 {
11478                         rsurface.lightmaptexture = NULL;
11479                         rsurface.deluxemaptexture = NULL;
11480                         rsurface.uselightmaptexture = false;
11481                         // simply scan ahead until we find a different texture or lightmap state
11482                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11483                                 ;
11484                 }
11485                 else
11486                 {
11487                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11488                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11489                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11490                         // simply scan ahead until we find a different texture or lightmap state
11491                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11492                                 ;
11493                 }
11494                 // render the range of surfaces
11495                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11496         }
11497         R_FrameData_ReturnToMark();
11498 }
11499
11500 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11501 {
11502         CHECKGLERROR
11503         if (depthonly)
11504                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11505         else if (prepass)
11506         {
11507                 if (!rsurface.texture->currentnumlayers)
11508                         return;
11509                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11510                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11511                 else
11512                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11513         }
11514         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11515                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11516         else if (!rsurface.texture->currentnumlayers)
11517                 return;
11518         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11519         {
11520                 // in the deferred case, transparent surfaces were queued during prepass
11521                 if (!r_shadow_usingdeferredprepass)
11522                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11523         }
11524         else
11525         {
11526                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11527                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11528         }
11529         CHECKGLERROR
11530 }
11531
11532 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11533 {
11534         int i, j;
11535         texture_t *texture;
11536         R_FrameData_SetMark();
11537         // break the surface list down into batches by texture and use of lightmapping
11538         for (i = 0;i < numsurfaces;i = j)
11539         {
11540                 j = i + 1;
11541                 // texture is the base texture pointer, rsurface.texture is the
11542                 // current frame/skin the texture is directing us to use (for example
11543                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11544                 // use skin 1 instead)
11545                 texture = surfacelist[i]->texture;
11546                 rsurface.texture = R_GetCurrentTexture(texture);
11547                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11548                 {
11549                         // if this texture is not the kind we want, skip ahead to the next one
11550                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11551                                 ;
11552                         continue;
11553                 }
11554                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11555                 {
11556                         rsurface.lightmaptexture = NULL;
11557                         rsurface.deluxemaptexture = NULL;
11558                         rsurface.uselightmaptexture = false;
11559                         // simply scan ahead until we find a different texture or lightmap state
11560                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11561                                 ;
11562                 }
11563                 else
11564                 {
11565                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11566                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11567                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11568                         // simply scan ahead until we find a different texture or lightmap state
11569                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11570                                 ;
11571                 }
11572                 // render the range of surfaces
11573                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11574         }
11575         R_FrameData_ReturnToMark();
11576 }
11577
11578 float locboxvertex3f[6*4*3] =
11579 {
11580         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11581         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11582         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11583         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11584         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11585         1,0,0, 0,0,0, 0,1,0, 1,1,0
11586 };
11587
11588 unsigned short locboxelements[6*2*3] =
11589 {
11590          0, 1, 2, 0, 2, 3,
11591          4, 5, 6, 4, 6, 7,
11592          8, 9,10, 8,10,11,
11593         12,13,14, 12,14,15,
11594         16,17,18, 16,18,19,
11595         20,21,22, 20,22,23
11596 };
11597
11598 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11599 {
11600         int i, j;
11601         cl_locnode_t *loc = (cl_locnode_t *)ent;
11602         vec3_t mins, size;
11603         float vertex3f[6*4*3];
11604         CHECKGLERROR
11605         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11606         GL_DepthMask(false);
11607         GL_DepthRange(0, 1);
11608         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11609         GL_DepthTest(true);
11610         GL_CullFace(GL_NONE);
11611         R_EntityMatrix(&identitymatrix);
11612
11613 //      R_Mesh_ResetTextureState();
11614
11615         i = surfacelist[0];
11616         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11617                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11618                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11619                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11620
11621         if (VectorCompare(loc->mins, loc->maxs))
11622         {
11623                 VectorSet(size, 2, 2, 2);
11624                 VectorMA(loc->mins, -0.5f, size, mins);
11625         }
11626         else
11627         {
11628                 VectorCopy(loc->mins, mins);
11629                 VectorSubtract(loc->maxs, loc->mins, size);
11630         }
11631
11632         for (i = 0;i < 6*4*3;)
11633                 for (j = 0;j < 3;j++, i++)
11634                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11635
11636         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11637         R_SetupShader_Generic_NoTexture(false, false);
11638         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11639 }
11640
11641 void R_DrawLocs(void)
11642 {
11643         int index;
11644         cl_locnode_t *loc, *nearestloc;
11645         vec3_t center;
11646         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11647         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11648         {
11649                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11650                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11651         }
11652 }
11653
11654 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11655 {
11656         if (decalsystem->decals)
11657                 Mem_Free(decalsystem->decals);
11658         memset(decalsystem, 0, sizeof(*decalsystem));
11659 }
11660
11661 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)
11662 {
11663         tridecal_t *decal;
11664         tridecal_t *decals;
11665         int i;
11666
11667         // expand or initialize the system
11668         if (decalsystem->maxdecals <= decalsystem->numdecals)
11669         {
11670                 decalsystem_t old = *decalsystem;
11671                 qboolean useshortelements;
11672                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11673                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11674                 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)));
11675                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11676                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11677                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11678                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11679                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11680                 if (decalsystem->numdecals)
11681                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11682                 if (old.decals)
11683                         Mem_Free(old.decals);
11684                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11685                         decalsystem->element3i[i] = i;
11686                 if (useshortelements)
11687                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11688                                 decalsystem->element3s[i] = i;
11689         }
11690
11691         // grab a decal and search for another free slot for the next one
11692         decals = decalsystem->decals;
11693         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11694         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11695                 ;
11696         decalsystem->freedecal = i;
11697         if (decalsystem->numdecals <= i)
11698                 decalsystem->numdecals = i + 1;
11699
11700         // initialize the decal
11701         decal->lived = 0;
11702         decal->triangleindex = triangleindex;
11703         decal->surfaceindex = surfaceindex;
11704         decal->decalsequence = decalsequence;
11705         decal->color4f[0][0] = c0[0];
11706         decal->color4f[0][1] = c0[1];
11707         decal->color4f[0][2] = c0[2];
11708         decal->color4f[0][3] = 1;
11709         decal->color4f[1][0] = c1[0];
11710         decal->color4f[1][1] = c1[1];
11711         decal->color4f[1][2] = c1[2];
11712         decal->color4f[1][3] = 1;
11713         decal->color4f[2][0] = c2[0];
11714         decal->color4f[2][1] = c2[1];
11715         decal->color4f[2][2] = c2[2];
11716         decal->color4f[2][3] = 1;
11717         decal->vertex3f[0][0] = v0[0];
11718         decal->vertex3f[0][1] = v0[1];
11719         decal->vertex3f[0][2] = v0[2];
11720         decal->vertex3f[1][0] = v1[0];
11721         decal->vertex3f[1][1] = v1[1];
11722         decal->vertex3f[1][2] = v1[2];
11723         decal->vertex3f[2][0] = v2[0];
11724         decal->vertex3f[2][1] = v2[1];
11725         decal->vertex3f[2][2] = v2[2];
11726         decal->texcoord2f[0][0] = t0[0];
11727         decal->texcoord2f[0][1] = t0[1];
11728         decal->texcoord2f[1][0] = t1[0];
11729         decal->texcoord2f[1][1] = t1[1];
11730         decal->texcoord2f[2][0] = t2[0];
11731         decal->texcoord2f[2][1] = t2[1];
11732         TriangleNormal(v0, v1, v2, decal->plane);
11733         VectorNormalize(decal->plane);
11734         decal->plane[3] = DotProduct(v0, decal->plane);
11735 }
11736
11737 extern cvar_t cl_decals_bias;
11738 extern cvar_t cl_decals_models;
11739 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11740 // baseparms, parms, temps
11741 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)
11742 {
11743         int cornerindex;
11744         int index;
11745         float v[9][3];
11746         const float *vertex3f;
11747         const float *normal3f;
11748         int numpoints;
11749         float points[2][9][3];
11750         float temp[3];
11751         float tc[9][2];
11752         float f;
11753         float c[9][4];
11754         const int *e;
11755
11756         e = rsurface.modelelement3i + 3*triangleindex;
11757
11758         vertex3f = rsurface.modelvertex3f;
11759         normal3f = rsurface.modelnormal3f;
11760
11761         if (normal3f)
11762         {
11763                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11764                 {
11765                         index = 3*e[cornerindex];
11766                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11767                 }
11768         }
11769         else
11770         {
11771                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11772                 {
11773                         index = 3*e[cornerindex];
11774                         VectorCopy(vertex3f + index, v[cornerindex]);
11775                 }
11776         }
11777
11778         // cull backfaces
11779         //TriangleNormal(v[0], v[1], v[2], normal);
11780         //if (DotProduct(normal, localnormal) < 0.0f)
11781         //      continue;
11782         // clip by each of the box planes formed from the projection matrix
11783         // if anything survives, we emit the decal
11784         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]);
11785         if (numpoints < 3)
11786                 return;
11787         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]);
11788         if (numpoints < 3)
11789                 return;
11790         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]);
11791         if (numpoints < 3)
11792                 return;
11793         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]);
11794         if (numpoints < 3)
11795                 return;
11796         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]);
11797         if (numpoints < 3)
11798                 return;
11799         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]);
11800         if (numpoints < 3)
11801                 return;
11802         // some part of the triangle survived, so we have to accept it...
11803         if (dynamic)
11804         {
11805                 // dynamic always uses the original triangle
11806                 numpoints = 3;
11807                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11808                 {
11809                         index = 3*e[cornerindex];
11810                         VectorCopy(vertex3f + index, v[cornerindex]);
11811                 }
11812         }
11813         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11814         {
11815                 // convert vertex positions to texcoords
11816                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11817                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11818                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11819                 // calculate distance fade from the projection origin
11820                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11821                 f = bound(0.0f, f, 1.0f);
11822                 c[cornerindex][0] = r * f;
11823                 c[cornerindex][1] = g * f;
11824                 c[cornerindex][2] = b * f;
11825                 c[cornerindex][3] = 1.0f;
11826                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11827         }
11828         if (dynamic)
11829                 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);
11830         else
11831                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11832                         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);
11833 }
11834 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)
11835 {
11836         matrix4x4_t projection;
11837         decalsystem_t *decalsystem;
11838         qboolean dynamic;
11839         dp_model_t *model;
11840         const msurface_t *surface;
11841         const msurface_t *surfaces;
11842         const int *surfacelist;
11843         const texture_t *texture;
11844         int numtriangles;
11845         int numsurfacelist;
11846         int surfacelistindex;
11847         int surfaceindex;
11848         int triangleindex;
11849         float localorigin[3];
11850         float localnormal[3];
11851         float localmins[3];
11852         float localmaxs[3];
11853         float localsize;
11854         //float normal[3];
11855         float planes[6][4];
11856         float angles[3];
11857         bih_t *bih;
11858         int bih_triangles_count;
11859         int bih_triangles[256];
11860         int bih_surfaces[256];
11861
11862         decalsystem = &ent->decalsystem;
11863         model = ent->model;
11864         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11865         {
11866                 R_DecalSystem_Reset(&ent->decalsystem);
11867                 return;
11868         }
11869
11870         if (!model->brush.data_leafs && !cl_decals_models.integer)
11871         {
11872                 if (decalsystem->model)
11873                         R_DecalSystem_Reset(decalsystem);
11874                 return;
11875         }
11876
11877         if (decalsystem->model != model)
11878                 R_DecalSystem_Reset(decalsystem);
11879         decalsystem->model = model;
11880
11881         RSurf_ActiveModelEntity(ent, true, false, false);
11882
11883         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11884         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11885         VectorNormalize(localnormal);
11886         localsize = worldsize*rsurface.inversematrixscale;
11887         localmins[0] = localorigin[0] - localsize;
11888         localmins[1] = localorigin[1] - localsize;
11889         localmins[2] = localorigin[2] - localsize;
11890         localmaxs[0] = localorigin[0] + localsize;
11891         localmaxs[1] = localorigin[1] + localsize;
11892         localmaxs[2] = localorigin[2] + localsize;
11893
11894         //VectorCopy(localnormal, planes[4]);
11895         //VectorVectors(planes[4], planes[2], planes[0]);
11896         AnglesFromVectors(angles, localnormal, NULL, false);
11897         AngleVectors(angles, planes[0], planes[2], planes[4]);
11898         VectorNegate(planes[0], planes[1]);
11899         VectorNegate(planes[2], planes[3]);
11900         VectorNegate(planes[4], planes[5]);
11901         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11902         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11903         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11904         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11905         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11906         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11907
11908 #if 1
11909 // works
11910 {
11911         matrix4x4_t forwardprojection;
11912         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11913         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11914 }
11915 #else
11916 // broken
11917 {
11918         float projectionvector[4][3];
11919         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11920         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11921         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11922         projectionvector[0][0] = planes[0][0] * ilocalsize;
11923         projectionvector[0][1] = planes[1][0] * ilocalsize;
11924         projectionvector[0][2] = planes[2][0] * ilocalsize;
11925         projectionvector[1][0] = planes[0][1] * ilocalsize;
11926         projectionvector[1][1] = planes[1][1] * ilocalsize;
11927         projectionvector[1][2] = planes[2][1] * ilocalsize;
11928         projectionvector[2][0] = planes[0][2] * ilocalsize;
11929         projectionvector[2][1] = planes[1][2] * ilocalsize;
11930         projectionvector[2][2] = planes[2][2] * ilocalsize;
11931         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11932         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11933         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11934         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11935 }
11936 #endif
11937
11938         dynamic = model->surfmesh.isanimated;
11939         numsurfacelist = model->nummodelsurfaces;
11940         surfacelist = model->sortedmodelsurfaces;
11941         surfaces = model->data_surfaces;
11942
11943         bih = NULL;
11944         bih_triangles_count = -1;
11945         if(!dynamic)
11946         {
11947                 if(model->render_bih.numleafs)
11948                         bih = &model->render_bih;
11949                 else if(model->collision_bih.numleafs)
11950                         bih = &model->collision_bih;
11951         }
11952         if(bih)
11953                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11954         if(bih_triangles_count == 0)
11955                 return;
11956         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11957                 return;
11958         if(bih_triangles_count > 0)
11959         {
11960                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11961                 {
11962                         surfaceindex = bih_surfaces[triangleindex];
11963                         surface = surfaces + surfaceindex;
11964                         texture = surface->texture;
11965                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11966                                 continue;
11967                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11968                                 continue;
11969                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11970                 }
11971         }
11972         else
11973         {
11974                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11975                 {
11976                         surfaceindex = surfacelist[surfacelistindex];
11977                         surface = surfaces + surfaceindex;
11978                         // check cull box first because it rejects more than any other check
11979                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11980                                 continue;
11981                         // skip transparent surfaces
11982                         texture = surface->texture;
11983                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11984                                 continue;
11985                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11986                                 continue;
11987                         numtriangles = surface->num_triangles;
11988                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11989                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11990                 }
11991         }
11992 }
11993
11994 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11995 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)
11996 {
11997         int renderentityindex;
11998         float worldmins[3];
11999         float worldmaxs[3];
12000         entity_render_t *ent;
12001
12002         if (!cl_decals_newsystem.integer)
12003                 return;
12004
12005         worldmins[0] = worldorigin[0] - worldsize;
12006         worldmins[1] = worldorigin[1] - worldsize;
12007         worldmins[2] = worldorigin[2] - worldsize;
12008         worldmaxs[0] = worldorigin[0] + worldsize;
12009         worldmaxs[1] = worldorigin[1] + worldsize;
12010         worldmaxs[2] = worldorigin[2] + worldsize;
12011
12012         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12013
12014         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12015         {
12016                 ent = r_refdef.scene.entities[renderentityindex];
12017                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12018                         continue;
12019
12020                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12021         }
12022 }
12023
12024 typedef struct r_decalsystem_splatqueue_s
12025 {
12026         vec3_t worldorigin;
12027         vec3_t worldnormal;
12028         float color[4];
12029         float tcrange[4];
12030         float worldsize;
12031         unsigned int decalsequence;
12032 }
12033 r_decalsystem_splatqueue_t;
12034
12035 int r_decalsystem_numqueued = 0;
12036 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12037
12038 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)
12039 {
12040         r_decalsystem_splatqueue_t *queue;
12041
12042         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12043                 return;
12044
12045         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12046         VectorCopy(worldorigin, queue->worldorigin);
12047         VectorCopy(worldnormal, queue->worldnormal);
12048         Vector4Set(queue->color, r, g, b, a);
12049         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12050         queue->worldsize = worldsize;
12051         queue->decalsequence = cl.decalsequence++;
12052 }
12053
12054 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12055 {
12056         int i;
12057         r_decalsystem_splatqueue_t *queue;
12058
12059         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12060                 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);
12061         r_decalsystem_numqueued = 0;
12062 }
12063
12064 extern cvar_t cl_decals_max;
12065 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12066 {
12067         int i;
12068         decalsystem_t *decalsystem = &ent->decalsystem;
12069         int numdecals;
12070         unsigned int killsequence;
12071         tridecal_t *decal;
12072         float frametime;
12073         float lifetime;
12074
12075         if (!decalsystem->numdecals)
12076                 return;
12077
12078         if (r_showsurfaces.integer)
12079                 return;
12080
12081         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12082         {
12083                 R_DecalSystem_Reset(decalsystem);
12084                 return;
12085         }
12086
12087         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12088         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12089
12090         if (decalsystem->lastupdatetime)
12091                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12092         else
12093                 frametime = 0;
12094         decalsystem->lastupdatetime = r_refdef.scene.time;
12095         numdecals = decalsystem->numdecals;
12096
12097         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12098         {
12099                 if (decal->color4f[0][3])
12100                 {
12101                         decal->lived += frametime;
12102                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12103                         {
12104                                 memset(decal, 0, sizeof(*decal));
12105                                 if (decalsystem->freedecal > i)
12106                                         decalsystem->freedecal = i;
12107                         }
12108                 }
12109         }
12110         decal = decalsystem->decals;
12111         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12112                 numdecals--;
12113
12114         // collapse the array by shuffling the tail decals into the gaps
12115         for (;;)
12116         {
12117                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12118                         decalsystem->freedecal++;
12119                 if (decalsystem->freedecal == numdecals)
12120                         break;
12121                 decal[decalsystem->freedecal] = decal[--numdecals];
12122         }
12123
12124         decalsystem->numdecals = numdecals;
12125
12126         if (numdecals <= 0)
12127         {
12128                 // if there are no decals left, reset decalsystem
12129                 R_DecalSystem_Reset(decalsystem);
12130         }
12131 }
12132
12133 extern skinframe_t *decalskinframe;
12134 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12135 {
12136         int i;
12137         decalsystem_t *decalsystem = &ent->decalsystem;
12138         int numdecals;
12139         tridecal_t *decal;
12140         float faderate;
12141         float alpha;
12142         float *v3f;
12143         float *c4f;
12144         float *t2f;
12145         const int *e;
12146         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12147         int numtris = 0;
12148
12149         numdecals = decalsystem->numdecals;
12150         if (!numdecals)
12151                 return;
12152
12153         if (r_showsurfaces.integer)
12154                 return;
12155
12156         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12157         {
12158                 R_DecalSystem_Reset(decalsystem);
12159                 return;
12160         }
12161
12162         // if the model is static it doesn't matter what value we give for
12163         // wantnormals and wanttangents, so this logic uses only rules applicable
12164         // to a model, knowing that they are meaningless otherwise
12165         if (ent == r_refdef.scene.worldentity)
12166                 RSurf_ActiveWorldEntity();
12167         else
12168                 RSurf_ActiveModelEntity(ent, false, false, false);
12169
12170         decalsystem->lastupdatetime = r_refdef.scene.time;
12171
12172         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12173
12174         // update vertex positions for animated models
12175         v3f = decalsystem->vertex3f;
12176         c4f = decalsystem->color4f;
12177         t2f = decalsystem->texcoord2f;
12178         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12179         {
12180                 if (!decal->color4f[0][3])
12181                         continue;
12182
12183                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12184                         continue;
12185
12186                 // skip backfaces
12187                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12188                         continue;
12189
12190                 // update color values for fading decals
12191                 if (decal->lived >= cl_decals_time.value)
12192                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12193                 else
12194                         alpha = 1.0f;
12195
12196                 c4f[ 0] = decal->color4f[0][0] * alpha;
12197                 c4f[ 1] = decal->color4f[0][1] * alpha;
12198                 c4f[ 2] = decal->color4f[0][2] * alpha;
12199                 c4f[ 3] = 1;
12200                 c4f[ 4] = decal->color4f[1][0] * alpha;
12201                 c4f[ 5] = decal->color4f[1][1] * alpha;
12202                 c4f[ 6] = decal->color4f[1][2] * alpha;
12203                 c4f[ 7] = 1;
12204                 c4f[ 8] = decal->color4f[2][0] * alpha;
12205                 c4f[ 9] = decal->color4f[2][1] * alpha;
12206                 c4f[10] = decal->color4f[2][2] * alpha;
12207                 c4f[11] = 1;
12208
12209                 t2f[0] = decal->texcoord2f[0][0];
12210                 t2f[1] = decal->texcoord2f[0][1];
12211                 t2f[2] = decal->texcoord2f[1][0];
12212                 t2f[3] = decal->texcoord2f[1][1];
12213                 t2f[4] = decal->texcoord2f[2][0];
12214                 t2f[5] = decal->texcoord2f[2][1];
12215
12216                 // update vertex positions for animated models
12217                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12218                 {
12219                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12220                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12221                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12222                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12223                 }
12224                 else
12225                 {
12226                         VectorCopy(decal->vertex3f[0], v3f);
12227                         VectorCopy(decal->vertex3f[1], v3f + 3);
12228                         VectorCopy(decal->vertex3f[2], v3f + 6);
12229                 }
12230
12231                 if (r_refdef.fogenabled)
12232                 {
12233                         alpha = RSurf_FogVertex(v3f);
12234                         VectorScale(c4f, alpha, c4f);
12235                         alpha = RSurf_FogVertex(v3f + 3);
12236                         VectorScale(c4f + 4, alpha, c4f + 4);
12237                         alpha = RSurf_FogVertex(v3f + 6);
12238                         VectorScale(c4f + 8, alpha, c4f + 8);
12239                 }
12240
12241                 v3f += 9;
12242                 c4f += 12;
12243                 t2f += 6;
12244                 numtris++;
12245         }
12246
12247         if (numtris > 0)
12248         {
12249                 r_refdef.stats[r_stat_drawndecals] += numtris;
12250
12251                 // now render the decals all at once
12252                 // (this assumes they all use one particle font texture!)
12253                 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);
12254 //              R_Mesh_ResetTextureState();
12255                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12256                 GL_DepthMask(false);
12257                 GL_DepthRange(0, 1);
12258                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12259                 GL_DepthTest(true);
12260                 GL_CullFace(GL_NONE);
12261                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12262                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12263                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12264         }
12265 }
12266
12267 static void R_DrawModelDecals(void)
12268 {
12269         int i, numdecals;
12270
12271         // fade faster when there are too many decals
12272         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12273         for (i = 0;i < r_refdef.scene.numentities;i++)
12274                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12275
12276         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12277         for (i = 0;i < r_refdef.scene.numentities;i++)
12278                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12279                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12280
12281         R_DecalSystem_ApplySplatEntitiesQueue();
12282
12283         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12284         for (i = 0;i < r_refdef.scene.numentities;i++)
12285                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12286
12287         r_refdef.stats[r_stat_totaldecals] += numdecals;
12288
12289         if (r_showsurfaces.integer)
12290                 return;
12291
12292         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12293
12294         for (i = 0;i < r_refdef.scene.numentities;i++)
12295         {
12296                 if (!r_refdef.viewcache.entityvisible[i])
12297                         continue;
12298                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12299                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12300         }
12301 }
12302
12303 extern cvar_t mod_collision_bih;
12304 static void R_DrawDebugModel(void)
12305 {
12306         entity_render_t *ent = rsurface.entity;
12307         int i, j, flagsmask;
12308         const msurface_t *surface;
12309         dp_model_t *model = ent->model;
12310
12311         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12312                 return;
12313
12314         if (r_showoverdraw.value > 0)
12315         {
12316                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12317                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12318                 R_SetupShader_Generic_NoTexture(false, false);
12319                 GL_DepthTest(false);
12320                 GL_DepthMask(false);
12321                 GL_DepthRange(0, 1);
12322                 GL_BlendFunc(GL_ONE, GL_ONE);
12323                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12324                 {
12325                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12326                                 continue;
12327                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12328                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12329                         {
12330                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12331                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12332                                 if (!rsurface.texture->currentlayers->depthmask)
12333                                         GL_Color(c, 0, 0, 1.0f);
12334                                 else if (ent == r_refdef.scene.worldentity)
12335                                         GL_Color(c, c, c, 1.0f);
12336                                 else
12337                                         GL_Color(0, c, 0, 1.0f);
12338                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12339                                 RSurf_DrawBatch();
12340                         }
12341                 }
12342                 rsurface.texture = NULL;
12343         }
12344
12345         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12346
12347 //      R_Mesh_ResetTextureState();
12348         R_SetupShader_Generic_NoTexture(false, false);
12349         GL_DepthRange(0, 1);
12350         GL_DepthTest(!r_showdisabledepthtest.integer);
12351         GL_DepthMask(false);
12352         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12353
12354         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12355         {
12356                 int triangleindex;
12357                 int bihleafindex;
12358                 qboolean cullbox = false;
12359                 const q3mbrush_t *brush;
12360                 const bih_t *bih = &model->collision_bih;
12361                 const bih_leaf_t *bihleaf;
12362                 float vertex3f[3][3];
12363                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12364                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12365                 {
12366                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12367                                 continue;
12368                         switch (bihleaf->type)
12369                         {
12370                         case BIH_BRUSH:
12371                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12372                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12373                                 {
12374                                         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);
12375                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12376                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12377                                 }
12378                                 break;
12379                         case BIH_COLLISIONTRIANGLE:
12380                                 triangleindex = bihleaf->itemindex;
12381                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12382                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12383                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12384                                 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);
12385                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12386                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12387                                 break;
12388                         case BIH_RENDERTRIANGLE:
12389                                 triangleindex = bihleaf->itemindex;
12390                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12391                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12392                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12393                                 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);
12394                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12395                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12396                                 break;
12397                         }
12398                 }
12399         }
12400
12401         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12402
12403 #ifndef USE_GLES2
12404         if (r_showtris.integer && qglPolygonMode)
12405         {
12406                 if (r_showdisabledepthtest.integer)
12407                 {
12408                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12409                         GL_DepthMask(false);
12410                 }
12411                 else
12412                 {
12413                         GL_BlendFunc(GL_ONE, GL_ZERO);
12414                         GL_DepthMask(true);
12415                 }
12416                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12417                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12418                 {
12419                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12420                                 continue;
12421                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12422                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12423                         {
12424                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12425                                 if (!rsurface.texture->currentlayers->depthmask)
12426                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12427                                 else if (ent == r_refdef.scene.worldentity)
12428                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12429                                 else
12430                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12431                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12432                                 RSurf_DrawBatch();
12433                         }
12434                 }
12435                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12436                 rsurface.texture = NULL;
12437         }
12438
12439         if (r_shownormals.value != 0 && qglBegin)
12440         {
12441                 int l, k;
12442                 vec3_t v;
12443                 if (r_showdisabledepthtest.integer)
12444                 {
12445                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12446                         GL_DepthMask(false);
12447                 }
12448                 else
12449                 {
12450                         GL_BlendFunc(GL_ONE, GL_ZERO);
12451                         GL_DepthMask(true);
12452                 }
12453                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12454                 {
12455                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12456                                 continue;
12457                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12458                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12459                         {
12460                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12461                                 qglBegin(GL_LINES);
12462                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12463                                 {
12464                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12465                                         {
12466                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12467                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12468                                                 qglVertex3f(v[0], v[1], v[2]);
12469                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12470                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12471                                                 qglVertex3f(v[0], v[1], v[2]);
12472                                         }
12473                                 }
12474                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12475                                 {
12476                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12477                                         {
12478                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12479                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12480                                                 qglVertex3f(v[0], v[1], v[2]);
12481                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12482                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12483                                                 qglVertex3f(v[0], v[1], v[2]);
12484                                         }
12485                                 }
12486                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
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, r_refdef.view.colorscale, 0, 1);
12492                                                 qglVertex3f(v[0], v[1], v[2]);
12493                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + 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.batchnormal3f)
12499                                 {
12500                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12501                                         {
12502                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12503                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12504                                                 qglVertex3f(v[0], v[1], v[2]);
12505                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + 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                                 qglEnd();
12511                                 CHECKGLERROR
12512                         }
12513                 }
12514                 rsurface.texture = NULL;
12515         }
12516 #endif
12517 }
12518
12519 int r_maxsurfacelist = 0;
12520 const msurface_t **r_surfacelist = NULL;
12521 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12522 {
12523         int i, j, endj, flagsmask;
12524         dp_model_t *model = r_refdef.scene.worldmodel;
12525         msurface_t *surfaces;
12526         unsigned char *update;
12527         int numsurfacelist = 0;
12528         if (model == NULL)
12529                 return;
12530
12531         if (r_maxsurfacelist < model->num_surfaces)
12532         {
12533                 r_maxsurfacelist = model->num_surfaces;
12534                 if (r_surfacelist)
12535                         Mem_Free((msurface_t**)r_surfacelist);
12536                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12537         }
12538
12539         RSurf_ActiveWorldEntity();
12540
12541         surfaces = model->data_surfaces;
12542         update = model->brushq1.lightmapupdateflags;
12543
12544         // update light styles on this submodel
12545         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12546         {
12547                 model_brush_lightstyleinfo_t *style;
12548                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12549                 {
12550                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12551                         {
12552                                 int *list = style->surfacelist;
12553                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12554                                 for (j = 0;j < style->numsurfaces;j++)
12555                                         update[list[j]] = true;
12556                         }
12557                 }
12558         }
12559
12560         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12561
12562         if (debug)
12563         {
12564                 R_DrawDebugModel();
12565                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12566                 return;
12567         }
12568
12569         rsurface.lightmaptexture = NULL;
12570         rsurface.deluxemaptexture = NULL;
12571         rsurface.uselightmaptexture = false;
12572         rsurface.texture = NULL;
12573         rsurface.rtlight = NULL;
12574         numsurfacelist = 0;
12575         // add visible surfaces to draw list
12576         for (i = 0;i < model->nummodelsurfaces;i++)
12577         {
12578                 j = model->sortedmodelsurfaces[i];
12579                 if (r_refdef.viewcache.world_surfacevisible[j])
12580                         r_surfacelist[numsurfacelist++] = surfaces + j;
12581         }
12582         // update lightmaps if needed
12583         if (model->brushq1.firstrender)
12584         {
12585                 model->brushq1.firstrender = false;
12586                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12587                         if (update[j])
12588                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12589         }
12590         else if (update)
12591         {
12592                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12593                         if (r_refdef.viewcache.world_surfacevisible[j])
12594                                 if (update[j])
12595                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12596         }
12597         // don't do anything if there were no surfaces
12598         if (!numsurfacelist)
12599         {
12600                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12601                 return;
12602         }
12603         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12604
12605         // add to stats if desired
12606         if (r_speeds.integer && !skysurfaces && !depthonly)
12607         {
12608                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12609                 for (j = 0;j < numsurfacelist;j++)
12610                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12611         }
12612
12613         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12614 }
12615
12616 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12617 {
12618         int i, j, endj, flagsmask;
12619         dp_model_t *model = ent->model;
12620         msurface_t *surfaces;
12621         unsigned char *update;
12622         int numsurfacelist = 0;
12623         if (model == NULL)
12624                 return;
12625
12626         if (r_maxsurfacelist < model->num_surfaces)
12627         {
12628                 r_maxsurfacelist = model->num_surfaces;
12629                 if (r_surfacelist)
12630                         Mem_Free((msurface_t **)r_surfacelist);
12631                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12632         }
12633
12634         // if the model is static it doesn't matter what value we give for
12635         // wantnormals and wanttangents, so this logic uses only rules applicable
12636         // to a model, knowing that they are meaningless otherwise
12637         if (ent == r_refdef.scene.worldentity)
12638                 RSurf_ActiveWorldEntity();
12639         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12640                 RSurf_ActiveModelEntity(ent, false, false, false);
12641         else if (prepass)
12642                 RSurf_ActiveModelEntity(ent, true, true, true);
12643         else if (depthonly)
12644         {
12645                 switch (vid.renderpath)
12646                 {
12647                 case RENDERPATH_GL20:
12648                 case RENDERPATH_D3D9:
12649                 case RENDERPATH_D3D10:
12650                 case RENDERPATH_D3D11:
12651                 case RENDERPATH_SOFT:
12652                 case RENDERPATH_GLES2:
12653                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12654                         break;
12655                 case RENDERPATH_GL11:
12656                 case RENDERPATH_GL13:
12657                 case RENDERPATH_GLES1:
12658                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12659                         break;
12660                 }
12661         }
12662         else
12663         {
12664                 switch (vid.renderpath)
12665                 {
12666                 case RENDERPATH_GL20:
12667                 case RENDERPATH_D3D9:
12668                 case RENDERPATH_D3D10:
12669                 case RENDERPATH_D3D11:
12670                 case RENDERPATH_SOFT:
12671                 case RENDERPATH_GLES2:
12672                         RSurf_ActiveModelEntity(ent, true, true, false);
12673                         break;
12674                 case RENDERPATH_GL11:
12675                 case RENDERPATH_GL13:
12676                 case RENDERPATH_GLES1:
12677                         RSurf_ActiveModelEntity(ent, true, false, false);
12678                         break;
12679                 }
12680         }
12681
12682         surfaces = model->data_surfaces;
12683         update = model->brushq1.lightmapupdateflags;
12684
12685         // update light styles
12686         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12687         {
12688                 model_brush_lightstyleinfo_t *style;
12689                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12690                 {
12691                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12692                         {
12693                                 int *list = style->surfacelist;
12694                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12695                                 for (j = 0;j < style->numsurfaces;j++)
12696                                         update[list[j]] = true;
12697                         }
12698                 }
12699         }
12700
12701         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12702
12703         if (debug)
12704         {
12705                 R_DrawDebugModel();
12706                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12707                 return;
12708         }
12709
12710         rsurface.lightmaptexture = NULL;
12711         rsurface.deluxemaptexture = NULL;
12712         rsurface.uselightmaptexture = false;
12713         rsurface.texture = NULL;
12714         rsurface.rtlight = NULL;
12715         numsurfacelist = 0;
12716         // add visible surfaces to draw list
12717         for (i = 0;i < model->nummodelsurfaces;i++)
12718                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12719         // don't do anything if there were no surfaces
12720         if (!numsurfacelist)
12721         {
12722                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12723                 return;
12724         }
12725         // update lightmaps if needed
12726         if (update)
12727         {
12728                 int updated = 0;
12729                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12730                 {
12731                         if (update[j])
12732                         {
12733                                 updated++;
12734                                 R_BuildLightMap(ent, surfaces + j);
12735                         }
12736                 }
12737         }
12738
12739         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12740
12741         // add to stats if desired
12742         if (r_speeds.integer && !skysurfaces && !depthonly)
12743         {
12744                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12745                 for (j = 0;j < numsurfacelist;j++)
12746                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12747         }
12748
12749         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12750 }
12751
12752 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12753 {
12754         static texture_t texture;
12755         static msurface_t surface;
12756         const msurface_t *surfacelist = &surface;
12757
12758         // fake enough texture and surface state to render this geometry
12759
12760         texture.update_lastrenderframe = -1; // regenerate this texture
12761         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12762         texture.basealpha = 1.0f;
12763         texture.currentskinframe = skinframe;
12764         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12765         texture.offsetmapping = OFFSETMAPPING_OFF;
12766         texture.offsetscale = 1;
12767         texture.specularscalemod = 1;
12768         texture.specularpowermod = 1;
12769         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12770         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12771         // JUST GREP FOR "specularscalemod = 1".
12772
12773         surface.texture = &texture;
12774         surface.num_triangles = numtriangles;
12775         surface.num_firsttriangle = firsttriangle;
12776         surface.num_vertices = numvertices;
12777         surface.num_firstvertex = firstvertex;
12778
12779         // now render it
12780         rsurface.texture = R_GetCurrentTexture(surface.texture);
12781         rsurface.lightmaptexture = NULL;
12782         rsurface.deluxemaptexture = NULL;
12783         rsurface.uselightmaptexture = false;
12784         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12785 }
12786
12787 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)
12788 {
12789         static msurface_t surface;
12790         const msurface_t *surfacelist = &surface;
12791
12792         // fake enough texture and surface state to render this geometry
12793         surface.texture = texture;
12794         surface.num_triangles = numtriangles;
12795         surface.num_firsttriangle = firsttriangle;
12796         surface.num_vertices = numvertices;
12797         surface.num_firstvertex = firstvertex;
12798
12799         // now render it
12800         rsurface.texture = R_GetCurrentTexture(surface.texture);
12801         rsurface.lightmaptexture = NULL;
12802         rsurface.deluxemaptexture = NULL;
12803         rsurface.uselightmaptexture = false;
12804         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12805 }